# Manage contract lifecycle transitions Source: https://docs.metronome.com/guides/customers-billing/manage-customers/manage-customer-lifecycle This use case walks through examples of how to use Metronome to manage contract lifecycle transitions. Contract lifecycle transitions happen when the relationship between a business and their customers changes. For example, after the initial signing of a deal, alterations like mid-term upsells, renewals, and the contract's expiration can occur. Metronome helps you manage the contract lifecycle, including the frictionless transitions between contract states. To support pricing and packaging flexibility for your organization, you can: * Create contracts that fully capture the agreed upon terms, pricing, and schedule * Update contracts to reflect new terms, upsells, downgrades, or new product launches * Conclude complex contracts and gate product usage * View a clear audit log of all contract lifecycle changes The examples on this page show how Metronome supports contract lifecycle management through the lens of different sales motions. ## Create an enterprise contract motion The terms of an enterprise contract can vary from one customer to another. Terms could include special access to non-public products, discounts on SKU-level list pricing, prepaid or postpaid commitments, and so on. Metronome supports an array of pricing and packaging motions, empowering your sales team to offer tailored deals without requiring IT or others to update the billing system. Metronome also powers your product entitlements workflow, ensuring that only a customer with an active contract can use your company's products and services. For example, your organization's sales team just offered a 1 year enterprise contract to a company named Moogle. The terms of the deal are a \$100,000 prepaid commitment for the right to use Product A starting on January 1st, 2025, with a discount of 10% off Product A's standard list price. To support this use case in Metronome: 1. Configure billable metrics to properly aggregate your customer’s usage. 2. Create products that represent the SKUs you’ll invoicing your customers for. 3. Set up a rate card to define your products’ standard pricing and entitlement. 4. Set up an integration with a downstream invoice provider like Stripe to support billing the customer. 5. Create a customer object representing Moogle. 6. Create a contract in Metronome associated with Moogle. You can create the contract with the [/contracts/create API](/api-reference/contracts/create-a-contract): ```bash theme={null} curl https://api.metronome.com/v1/contracts/create \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "450f7264-9b3d-43d5-8ee1-fc369a144c01", "name": "Enterprise Contract", "uniqueness_key": "1234", "rate_card_id": "6f06fad5-d017-4674-8b7f-1e00a1208109", "starting_at": "2025-01-01T00:00:00Z", "ending_before": "2026-01-01T00:00:00Z", "commits": [ { "type": "prepaid", "name": "Prepaid Commit Moogle", "product_id": "7bb1bdf6-e4af-42e0-be27-3cde86056919", "access_schedule": { "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "schedule_items": [ { "amount": 1000000, "starting_at": "2025-01-01T00:00:00Z", "ending_before": "2026-01-01T00:00:00Z" } ] }, "invoice_schedule": { "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "schedule_items": [ { "amount": 1000000, "timestamp": "2025-01-01T00:00:00Z" } ] }, "rollover_fraction": 0.5, "priority": 100, "applicable_product_ids": ["d6695114-299b-4bd7-b57c-7a9134ba50ae"] } ], "overrides": [ { "starting_at": "2025-01-01T00:00:00Z", "ending_before": "2026-01-01T00:00:00Z", "entitled": true, "type": "multiplier", "multiplier": 0.9, "product_id": "d6695114-299b-4bd7-b57c-7a9134ba50ae" } ] }' ``` After creating the contract, power your entitlement workflows with the `/contracts/get` API. For example, use the `/contracts/get` API to confirm Moogle's contract is active before allowing them to use Product A. ## Mid-term add-ons and renewals motion Opportunities often arise to capture more value from an existing business relationship. This typically manifests in the form of mid-term add-ons to an active contract, including access to new SKUs, new monetary commitments with variable list price discounting, and early contract renewals. Metronome helps your sales team capitalize on opportunities as they arise, enables your product teams to roll out and charge for new features, and saves your IT team from the stress of managing frequent and complex contractual changes. ### Execute a mid-term add-on Your company plans to beta launch Product B on October 1st, 2025. You offer a 20% discounted rate to your customer named Moogle in exchange for a new \$10,000 prepaid commitment. This \$10,000 prepaid commitment would only apply to use of Product B, and would begin on October 1st, 2025. To support this use case in Metronome: 1. Create a usage-based product representing Product B. 2. Update the existing rate card to include Product B with your list pricing and default entitlement. Set Product B's entitlement to **false** by default. This ensures that only customers with access to Product B are charged for its usage. 3. Edit the existing Moogle contract to: * Change Product B's entitlement to **true**, scheduled for October 1st, 2025 * Add a new prepaid commit to the existing contract for \$10,000 scheduled for October 1st, 2025, configured so that only usage for Product B gets drawn down * Override the list rate for Product B to give a 20% discount to Moogle Edit the contract with the [/contracts/edit API](/api-reference/contracts/edit-a-contract): ```bash theme={null} curl https://api.metronome.com/v2/contracts/edit \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "450f7264-9b3d-43d5-8ee1-fc369a144c01", "contract_id": "7b347536-56ac-4036-b5d1-67142b0d00e5", "add_commits": [ { "type": "prepaid", "name": "mid-term prepaid commit", "product_id": "7bb1bdf6-e4af-42e0-be27-3cde86056919", "access_schedule": { "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "schedule_items": [ { "amount": 1000000, "starting_at": "2025-10-01T00:00:00Z", "ending_before": "2026-01-01T00:00:00Z" } ] }, "invoice_schedule": { "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "schedule_items": [ { "amount": 1000000, "timestamp": "2025-10-01T00:00:00Z" } ] }, "rollover_fraction": 0.5, "priority": 100, "applicable_product_ids": ["f0608ff2-30b6-4010-b2a6-bada4296b8a0"] } ], "add_overrides": [ { "starting_at": "2025-10-01T00:00:00Z", "ending_before": "2026-01-01T00:00:00Z", "type": "multiplier", "multiplier": 0.8, "product_id": "f0608ff2-30b6-4010-b2a6-bada4296b8a0", "entitled": true } ] }' ``` ### Contract renewal Imagine it's now December 1st, 2025, meaning that Moogle has 1 month left on their existing contract. They're mostly satisfied with your services, and want to renew their contract to begin on January 1st, 2026 for another year. However, Moogle still has \$10,000 of prepaid commit remaining for Product A. Per the initial contract's details, the rollover percentage was set to 50% of the original balance in the event of a renewal. As \$10,000 is less than 50% of \$100,000, all \$10,000 of the remaining commit will roll over. Moogle likes this agreement, and renews with an additional \$200,000 prepaid commit for the combined usage of Product A and Product B. To support this use case in Metronome, create a new contract scheduled to begin on January 1st, 2026: 1. Assign the contract transition type **renewal** and link to the previous contract. 2. Add a prepaid commitment for \$200,000 configured to burn down as Product A and Product B get used. 3. Assume that one \$200,000 invoice gets sent on the contract start date (Jan 1st, 2026). On January 1st, 2026, the remaining \$10,000 in prepaid commit for Product A's usage rolls over to the new contract. This means that Moogle has two commits: one \$10,000 rollover commit solely for Product A's usage, and one \$200,000 prepaid commit for both Product A and Product B's usage. On this new contract, the \$10,000 rollover commit gets burned down first, before the \$200,000 commit is used. Complete the renewal with the `/contracts/create` API: ```bash theme={null} curl https://api.metronome.com/v1/contracts/create \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "450f7264-9b3d-43d5-8ee1-fc369a144c01", "name": "Enterprise Contract Renewal", "uniqueness_key": "12345", "rate_card_id": "6f06fad5-d017-4674-8b7f-1e00a1208109", "starting_at": "2026-01-01T00:00:00Z", "ending_before": "2027-01-01T00:00:00Z", "commits": [ { "type": "prepaid", "name": "renewal prepaid commit", "product_id": "7bb1bdf6-e4af-42e0-be27-3cde86056919", "access_schedule": { "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "schedule_items": [ { "amount": 20000000, "starting_at": "2026-01-01T00:00:00Z", "ending_before": "2027-01-01T00:00:00Z" } ] }, "invoice_schedule": { "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "schedule_items": [ { "amount": 20000000, "timestamp": "2026-01-01T00:00:00Z" } ] }, "rollover_fraction": 0.5, "priority": 101, "applicable_product_ids": [ "d6695114-299b-4bd7-b57c-7a9134ba50ae", "f0608ff2-30b6-4010-b2a6-bada4296b8a0" ] } ], "transition": { "type": "renewal", "from_contract_id": "7b347536-56ac-4036-b5d1-67142b0d00e5" } }' ``` ## End a contract motion The end of a business relationship involves two critical tasks: ensuring the financial obligations stated in the contract are met, and that access to your company's products and services get quickly gated. Metronome supports both requirements, as the system automatically tracks the contract's terms in relation to your customer's usage and offers features to power your product entitlements workflow. This means that if a contract concludes before the expected end date, the client receives an invoice for their remaining financial obligations while simultaneously sending a signal to your product entitlements system that the customer is no longer active. For example, Moogle decides to part ways with your company before using their entire prepaid commitment, and wants to exit the renewed contract on March 1st, 2026. To support this use case in Metronome: 1. Schedule the end date of the existing contract to be effective on March 1st, 2026. 2. Ensure that you gate access to your product at the time of contract end: * Set up an [alert](/guides/customers-billing/set-up-notifications/create-and-manage-notifications) to generate a webhook upon a commit reaching a low balance (in this case, \$0.00) * Configure your entitlement system to listen for the webhook and immediately gate access As this customer was invoiced for the prepaid commit at the time of contract start (January 1st, 2026), they already received their \$200,000 bill from your invoice provider. On March 1st, 2026, the contract's remaining prepaid commit goes to \$0.00. Update the contract end date with the [/contracts/updateEndDate API](/api-reference/contracts/update-the-contract-end-date): ```bash theme={null} curl https://api.metronome.com/v1/contracts/updateEndDate \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "450f7264-9b3d-43d5-8ee1-fc369a144c01", "contract_id": "7b347536-56ac-4036-b5d1-67142b0d00e5", "ending_before": "2026-03-01T00:00:00Z" }' ``` # Manage product access Source: https://docs.metronome.com/guides/customers-billing/manage-customers/manage-product-access
Metronome goes beyond the traditional borders of the Q2C stack by directly enhancing the customer experience within your product. Metronome encodes contract terms that define customer access through various packaging models, tracks entitlement status in real-time based on usage and payment, and alerts you to any changes in these entitlements.
Product access and entitlements
*** #### Provision a customer Learn how to provision a customer and assign a contract to them. This serves as the basis for encoding entitlements in Metronome. [Learn more >](/guides/get-started/core-concepts/provision-customer) *** #### Contract lifecycle transitions Manage the contract lifecycle to reflect the updated entitlements of a customer. This can be used to handle cases like renewals, upsells, and upgrade scenarios. [Learn more >](/guides/customers-billing/manage-customers/manage-customer-lifecycle) *** #### Create a trial Explore a common business model for providing temporary access to customers trying your product. This approach is typical in product-led growth (PLG) strategies, where you aim to streamline sign-ups while managing costs and encouraging customers to upgrade. [Learn more >](/guides/pricing-packaging/billing-model-guides/create-a-trial) *** #### Create and manage notifications Explore this feature that supports a wide range of use cases in Metronome and enables communication about changes in entitlement states. [Learn more >](/guides/customers-billing/set-up-notifications/create-and-manage-notifications) # Provision a customer Source: https://docs.metronome.com/guides/customers-billing/manage-customers/provision-a-customer In Metronome, customers are the recipients of an invoice and may represent individual users, enterprises, API keys, or whatever specification your organization needs. This guide describes how to provision a customer in Metronome. Provisioning your customer includes creating the customer object and configuring the associated contract that outlines their terms of use. A customer needs at least one contract provisioned to them to start metering and rating for billing. You can also configure multiple contracts per customer, if needed. ## Prerequisites Before provisioning a customer you must have: * Your [usage events](/guides/events/design-usage-events) connected to Metronome * A [billable metric](/guides/get-started/core-concepts/create-billable-metrics/) * A [product](/guides/get-started/core-concepts/create-products-contracts) * A [rate card](/guides/get-started/core-concepts/create-manage-rate-cards) ## Create a customer Create an individual customer object in Metronome or build a flow to create customers programmatically from system triggers. ### Understand ingest aliases Ingest aliases map your internal customer identifiers to Metronome's customer ID. When you send usage keyed on an ingest alias, Metronome automatically associates it to the correct Metronome customer. This allows you to maintain your existing customer entities without needing to swap in a Metronome customer ID. Ingest aliases can also be used to maintain account hierarchy. Enterprise customers often have sub-organizations that roll up to a single contract. Use ingest aliases to model this. For example, you can represent the enterprise organization as a customer in Metronome, with each sub-organization represented by an ingest alias attached to that customer: ``` Parent Account - Metronome Customer e7f893e5-07f7-483b-8c16-6905944c6a89 + Sub-Org 1 - IngestAlias1 + Sub-Org 2 - IngestAlias2 + Sub-Org 3 - IngestAlias3 + Sub-Org 4 - IngestAlias4 ``` You can split out each sub-organization's usage on the invoice Metronome generates. Learn how to use [group keys](/guides/get-started/core-concepts/create-billable-metrics#3-define-group-keys%E2%80%8B) to modify invoice presentation. Ingest aliases can be specified on the Metronome customer object at time of creation or any point after. Retroactively adding an ingest alias on the customer is a way to take Metronome out of the hot path of customer signup while properly metering usage. For example, if you first send usage keyed on `IngestAlias1` and later add this ingest alias to an existing customer, Metronome retroactively associates that usage to the correct customer. ### Create a customer with the Metronome app To create a customer using the app: 1. Go to the **Customers** page → **Add a customer**. 2. Add a name. 3. Add an ingest alias. 4. (Optional) Set a custom field for the customer on the **Settings** tab. ### Build a customer creation flow with the API Use the Metronome API to build a flow for creating customers in Metronome programmatically based on sales-led or product-led motions. For a sales-led motion, you might use Salesforce CPQ to capture opportunities. When an opportunity closes, you can schedule a job to create a customer using the Metronome API. This example request shows how to: * Create a mock customer, WidgetsExpress, in Metronome * Codify the relationship between the Metronome customer and the SFDC account by storing the `sfdc_account_id` in a custom field ```bash theme={null} curl https://api.metronome.com/v1/customers \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "ingest_aliases": [ "team@widgetsexpress.com" ], "name": "WidgetsExpress", "custom_fields": { "sfdc_account_id": "sfdc1001" } }' ``` For a product-led growth motion, create a similar workflow where the trigger originates from a signup on your website. Store the relationship between the Metronome customer and your internal customer object. ### Add a billing configuration to a customer A customer in Metronome can billed in different destinations, often depending on your billing motion. You must first create a `customer_billing_provider_configuration` on the customer and then assign it to a contract. Metronome allows you to configure multiple `customer_billing_provider_configurations` per customer, which means one customer can be billed in multiple systems - one per contract. **INFO** Before setting up a `customer_billing_provider_configuration`, Metronome must first be connected to the relevant system. Follow the steps in [Invoice with Stripe](/integrations/invoice-integrations/stripe) or [Invoice with the Marketplaces (AWS and Azure)](/integrations/marketplace-integrations/aws). Metronome recommends setting the `customer_billing_provider_configurations` on customer creation. For example, let's say WidgetsExpress purchased your product via AWS Marketplace. Amend the previous call to add a `customer_billing_provider_configurations` to the WidgetExpress customer: ```bash theme={null} curl https://api.metronome.com/v1/customers \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "ingest_aliases": [ "team@widgetsexpress.com" ], "name": "WidgetsExpress", "custom_fields": { "sfdc_account_id": "sfdc1001" }, "customer_billing_provider_configurations": [ { "billing_provider": "aws_marketplace", "configuration": { "aws_customer_id": "ABC123ABC12", "aws_product_code": "my_product", "aws_region": "us-west-1" }, "delivery_method": "direct_to_billing_provider" } ] }' ``` After submission, the customer will be created with the associated AWS configuration. However, it will not be billed to AWS until a contract is created with AWS set as the contract's `billing_provider_configuration`. If you do not set a `customer_billing_provider_configuration` on customer creation, you can add one later using the `/setCustomerBillingProviderConfigurations` endpoint. **BETA** You can archive a `customer_billing_provider_configuration` by either archiving the customer or archiving the specific configuration via the `/archiveCustomerBillingProviderConfigurations` endpoint. When you archive a billing configuration, it becomes available for reuse on a new customer. If you archive a `customer_billing_provider_configuration` that is attached to an active contract, the config will be archived on the contract immediately and no longer bill to the associated destination. A new `billing_provider_configuration` cannot be provisioned on the contract. ## Provision a customer contract Define a contract in Metronome that encodes the products customers can access, rates for each product, and access duration. Just as rate cards are built on products, contracts are built on rate cards. A contract references a specific rate card and bundles it with other Metronome models like [commits,](/guides/pricing-packaging/apply-credits-and-commits/create-a-pre-paid-commit) discounts, fixed products that don't live on the rate card, and more. Create contracts with the Metronome app or with the [/contracts/create endpoint](/api-reference/contracts/create-a-contract). ### Create a contract Consider an example where your customer, WidgetsExpress, purchased a prepaid commit for \$10,000 that applies to your cloud products via AWS Marketplace. This commit lasts for a year. As part of the contract, they also pay a \$1,000 platform fee each quarter to use your service. They pay for the prepaid commit once upfront and for usage on a monthly basis. To provision this contract with the [Metronome app](https://app.metronome.com/): 1. Navigate to *Customers* and select your newly created customer. 2. On the *Overview* tab, click the **+ Add** button on the right hand side of the *Contracts* pane. 3. Fill in the *Basic* info for the contract like the contract name, start date, and rate card to use. Be sure to set the billing provider to AWS. 4. Under *Terms*, click **Add -> Commit** and fill in the details for the prepaid commit. 5. Under *Terms*, click **Add -> Scheduled charges** and add the platform fee as a scheduled charge. The final contract looks like: Final contract To create the example contract with the `/contracts/create` API, execute this call: ```bash theme={null} curl https://api.metronome.com/v1/contracts/create \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "aa58107d-162f-407e-9f09-940f16adbb1c", "rate_card_alias": "base_usage_products", "starting_at": "2024-11-01T00:00:00.000Z", "billing_provider_configuration": { "billing_provider": "aws_marketplace", "delivery_method": "direct_to_billing_provider" }, "commits": [ { "type": "prepaid", "name": "Contract Prepaid Commit", "product_id": "a1f4e40b-f8c4-496b-b687-0a103396b479", "access_schedule": { "schedule_items": [ { "amount": 1000000, "starting_at": "2024-11-01T00:00:00.000Z", "ending_before": "2025-11-01T00:00:00.000Z" } ] }, "invoice_schedule": { "schedule_items": [ { "unit_price": 1000000, "quantity": 1, "timestamp": "2024-11-01T00:00:00.000Z" } ] }, "applicable_product_tags": ["cloud"], "description": "Usage Commit" } ], "scheduled_charges": [ { "product_id": "06cf3703-3f5e-467c-8ba1-0ee934c740b9", "name": "Platform Charge", "schedule": { "recurring_schedule": { "starting_at": "2024-11-01T00:00:00.000Z", "ending_before": "2025-11-01T00:00:00.000Z", "frequency": "quarterly", "unit_price": 100000, "quantity": 1, "amount_distribution": "each" } } } ], "usage_statement_schedule": { "frequency": "monthly", "day": "contract_start" } }' ``` ## Consolidate usage and scheduled invoices You have the option to specify if scheduled invoices should consolidate onto a customer's usage invoices. This setting applies to all charges (including commits) on the contract. It follows this logic to determine whether to consolidate invoices: * The last day of the usage service period (exclusive) falls on the same day as the scheduled date for the scheduled invoice. * The corresponding usage invoice hasn't finalized. Consolidation occurs at the time of contract creation and upon any contract changes in the future. Consider an example where a new customer buys the Best package on your website, which costs \$75 per month. As part of this package, they receive a \$100 monthly commit. The contract and recurring commit start on January 1 with no end date. If `scheduled_charges_on_usage_invoices` is set to `ALL`, the contract creates these invoices: * **Invoice 1:** Issued and finalized on January 1 with one line item for the \$75 monthly charge. * **Invoice 2:** Created in draft with one line item for the \$75 monthly charge in February in addition to all usage charges for January. * **Invoice X:** Assuming no changes to the contract, all future invoices will model invoice 2. ## Add contract discounts and overrides Provide discounts during contract creation or by editing an existing contract. Apply discounts with credits, [overrides for product rates](/guides/pricing-packaging/make-pricing-changes/edit-or-override-a-contract), price tiers, and more. If you use dimensional pricing, set price overrides for each combination of group key and product. To add additional terms like credits, commits, overrides for product rates, and more, edit the contract. Consider the example with your mock customer WidgetsExpress to see this in practice. The customer negotiated a discount on cloud products. To address this, edit the contract by overriding products with the `cloud` tag to be 5% off of the basic rate card. To edit a contract with the Metronome app, go to the WidgetsExpress customer → Contracts -> and select the contract that you would like to edit. To edit a contract through the API, execute this call: ```bash theme={null} curl https://api.metronome.com/v2/contracts/edit \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "aa58107d-162f-407e-9f09-940f16adbb1c", "contract_id": "0a6180da-336a-40e6-98f4-20b6be08211d", "add_overrides": [ { "starting_at": "2024-11-01T00:00:00.000Z", "entitled": true, "type": "multiplier", "multiplier": 0.95, "applicable_product_tags": ["cloud"] } ] }' ``` ## Create a usage filter You can provision a customer with multiple contracts simultaneously. These contracts can use distinct rate cards, have different start and end dates, discounts, and more. They can all draw down from shared customer-level commits and credits. To specify that usage should count against one contract instead of another, create a usage filter for that contract. For example, your mock customer WidgetsExpress has three sub-divisions: US, EU, and APAC. Each division negotiated different discounts. To model this in Metronome, create a contract for each sub-division and use usage filters to ensure only the appropriate usage gets routed to each contract. When creating the US contract, ensure that only events with the property `region` and value ` US` are included in this contract using this API call: ```bash theme={null} curl https://api.metronome.com/v1/contracts/create \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "13117714-3f05-48e5-a6e9-a66093f13b4d", "rate_card_id": "d7abd0cd-4ae9-4db7-8676-e986a4ebd8dc", "starting_at": "2024-10-01T00:00:00.000Z", "usage_filter": { "group_key": "region", "group_values": [ "US" ] } }' ``` You can update the usage filter on a contract at any time, on a schedule. For example, imagine that as of 2025, WidgetsExpress no longer wants usage within their EU division invoiced separately. Instead, they should get billed through the US contract, using US prices. This API call shows how to update the usage filter, with the edit taking effect on Jan 01, 2025: ```bash theme={null} curl https://api.metronome.com/v1/contracts/setUsageFilter \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "13117714-3f05-48e5-a6e9-a66093f13b4d", "contract_id": "d7abd0cd-4ae9-4db7-8676-e986a4ebd8dc", "group_key": "region", "group_values": ["US", "EU"], "starting_at": "2025-01-01T00:00:00.000Z" }' ``` Usage filters have these limitations: * For [streaming billable metrics](/guides/get-started/core-concepts/create-billable-metrics/), you must define the usage filter as a group key on the underlying billable metric. If you're also using dimensional pricing and presentation group keys, the usage filter group key must be defined in a compound group key on the underlying billable metric with the dimensional pricing and presentation group keys. * For [SQL billable metrics](/guides/get-started/core-concepts/create-billable-metrics#define-group-keys-on-sql-billable-metrics%E2%80%8B/), the group key for the usage filter must be present as property value in the underlying events (for example, `properties.region`). * `LATEST` billable metrics are not currently compatible with contract-level usage filters. Applying a contract-level usage filter to a contract that rates a product backed by a `LATEST` billable metric can cause invoice computation errors. Use `LATEST` only on contracts without usage filters. ## Add custom fields Use [custom fields](/developer-resources/custom-fields/) to add additional metadata to the contract or commit. This metadata can power downstream processes like revenue recognition workflows. For example, if you're integrating with SFDC, you can create a custom field for `salesforce_opportunity_id` to map Metronome contracts, and revenue derived from it, to the associated SFDC opportunity. # Schedule a billing provider change Source: https://docs.metronome.com/guides/customers-billing/manage-customers/schedule-billing-provider-change Switch billing providers on an existing contract without creating a new one. Schedule the addition, removal, correction, or switching of a billing provider on a contract. A contract stores a **billing provider configuration schedule** — an ordered list of segments each with an `effective_at` timestamp aligned to a billing period boundary. The active configuration for a given invoice is the segment with the latest `effective_at` date before the service period end date or `issued~at` date if there is no service period end date. ## Supported transitions | From → To | Current period | Next period | | :--------------------------------------- | :------------: | :---------: | | Stripe → Stripe | ✅ | ✅ | | Stripe → NetSuite | ✅ | ✅ | | Stripe → null | ✅ | ✅ | | NetSuite → Stripe | ✅ | ✅ | | NetSuite → null | ✅ | ✅ | | Stripe → Marketplace (AWS / Azure / GCP) | ❌ | ✅ | | Marketplace → Stripe | ❌ | ✅ | | Marketplace → Marketplace | ❌ | ✅ | | NetSuite → Marketplace | ❌ | ✅ | | Marketplace → NetSuite | ❌ | ✅ | | Marketplace → null | ❌ | ✅ | ## Schedule a change Use the `add_billing_provider_configuration_update` field on `POST v2/contracts/edit`. The `effective_at` controls when the new configuration takes effect: `START_OF_CURRENT_PERIOD` or `START_OF_NEXT_PERIOD`. **Example: Correct a Stripe misconfiguration, effective immediately** Switch from one Stripe configuration to another at the start of the current period. The current draft invoice will be routed to the new configuration. If an invoice was already finalized and sent to Stripe during this period, the new configuration will not apply to it — all invoices are guaranteed to be sent exactly once. ```bash theme={null} curl https://api.metronome.com/v2/contracts/edit \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "8cecbf69-960f-4f66-9575-edebb7d95e88", "contract_id": "6058587f-763c-400f-a822-3edb3eb2b86b", "add_billing_provider_configuration_update": { "billing_provider_configuration": { "billing_provider_configuration_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", }, "schedule": { "effective_at": "START_OF_CURRENT_PERIOD" } } }' ``` **Example: Transition from Stripe to AWS Marketplace, effective next period** All invoices from the current billing period are routed based on the existing Stripe configuration. The marketplace configuration takes effect at the start of the next period. ```bash theme={null} curl https://api.metronome.com/v2/contracts/edit \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "8cecbf69-960f-4f66-9575-edebb7d95e88", "contract_id": "6058587f-763c-400f-a822-3edb3eb2b86b", "add_billing_provider_configuration_update": { "billing_provider_configuration": { "billing_provider_configuration_id": "b2c3d4e5-f6a7-8901-bcde-f12345678901" }, "schedule": { "effective_at": "START_OF_NEXT_PERIOD" } }' ``` **Example: Transition from Stripe to no billing provider, effective current period** All invoices from the current billing period *will not* be routed to any downstream destination. ```bash theme={null} curl https://api.metronome.com/v2/contracts/edit \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "8cecbf69-960f-4f66-9575-edebb7d95e88", "contract_id": "6058587f-763c-400f-a822-3edb3eb2b86b", "add_billing_provider_configuration_update": { "billing_provider_configuration": { "billing_provider_configuration_id": null } "schedule": { "effective_at": "START_OF_CURRENT_PERIOD" } }' ``` ## View the billing provider configuration schedule Fetch a contract using `POST v2/contracts/get` to view the full schedule. The `customer_billing_provider_configuration` field returns the currently-active configuration unchanged. The `billing_provider_configuration_schedule` field returns an ordered list of all past, current, and future segments. ```json theme={null} { "data": { "id": "6058587f-763c-400f-a822-3edb3eb2b86b", "customer_id": "8cecbf69-960f-4f66-9575-edebb7d95e88", "customer_billing_provider_configuration": { "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "billing_provider": "stripe", "delivery_method": "direct_to_billing_provider" }, "billing_provider_configuration_schedule": [ { "billing_provider_configuration": { "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "billing_provider": "stripe", "delivery_method": "direct_to_billing_provider" }, "effective_at": "2025-01-01T00:00:00.000Z", "effective_until": "2025-06-01T00:00:00.000Z" }, { "billing_provider_configuration": { "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901", "billing_provider": "aws_marketplace", "delivery_method": "direct_to_billing_provider" }, "effective_at": "2025-06-01T00:00:00.000Z", "effective_until": null } ] } } ``` ## Constraints and considerations **Changes align to billing period boundaries.** `START_OF_CURRENT_PERIOD` resolves to the start of the current usage invoice service period. `START_OF_NEXT_PERIOD` resolves to the start of the following service period. Each invoice maps to exactly one billing provider configuration based on its service period start date. **Marketplace transitions require `START_OF_NEXT_PERIOD`.** Marketplace billing is metered from the start of a period, so mid-period transitions are not supported. When transitioning to a marketplace, the current period completes fully on the existing configuration. When transitioning away, the marketplace continues to bill through the end of the current period. **Threshold billing must be disabled before switching to a marketplace provider.** If a contract has an active threshold billing configuration, it must be removed before scheduling a transition to any marketplace provider. **`customer_billing_provider_configuration` is unchanged and backward compatible.** The existing field on `contracts/get` and `contracts/list` responses continues to return the currently-active configuration. No changes are required to existing integrations that read this field. **A maximum of 10 schedule segments per contract.** If you need additional capacity on a specific contract, contact your account team. **To cancel a scheduled future change**, schedule a new segment covering the same period. The latest segment takes precedence. # Spend trackers Source: https://docs.metronome.com/guides/customers-billing/manage-customers/spend-trackers **Public Beta** Spend trackers are currently in a Public Beta. Breaking changes may occur between now and GA. Please use the [Metronome support portal](https://support.metronome.com/) to request access. For certain billing models, it might be useful to track the spend of a customer over-time. These trackers might be used to inform discounting schemes or provide visibility to the end-customer. Create a `spend_tracker` on the contract to track the total spend for specific charges over time. ## Create a spend tracker Spend trackers return the summation of specified charges over a period of time - `spend_tracker.reset_frequency`. Spend trackers can be set on Package creation, contract creation, or contract edit. Other configurations on the contract can point at the spend tracker to manage spend based thresholds. For example, we can create a spend tracker to cap the amount of discounted prepaid commit purchases a customer can get in a single month. `applicable_spend_specifiers` specify which charges should count against the spend tracker: * *`spend_type`:* Today, only commit purchases can count towards a spend tracker. * *`sources`:* Specify whether commits created manually and / or threshold billing commits count towards the spend tracker. * *`discounted`:* Optionally specify whether commits marked as "discounted" count towards the spend tracker. For manual commits, this is defined via `spend_tracker_attributes.count_as_discounted`. For threshold billing commits, it is defined via the `discount_config`. See the example contract below: ```bash theme={null} curl https://api.metronome.com/v1/contracts/create \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "8cecbf69-960f-4f66-9575-edebb7d95e88", "rate_card_id": "a7bc3775-b651-46b6-b7e4-d225a7e55c4c", "starting_at": "2025-04-01T00:00:00.000Z", ... "spend_trackers": [ { "alias": "promo-cap", "credit_type_id": "usd_credit_type_id", "reset_frequency": "BILLING_PERIOD", "applicable_spend_specifiers": [ { "spend_type": "COMMIT_PURCHASE", "sources": ["THRESHOLD_RECHARGE", "MANUAL"], "discounted": "DISCOUNTED_ONLY" } ] } ], "prepaid_balance_threshold_configuration": { "commit": { "product_id": "d6be3bf4-1669-40c9-a8b1-388bb167ab16", "name": "prepaid-balance", "description": "threshold billing recharges" }, "discount_config": { "fraction": 0.90, "cap": { "spend_tracker_alias": "promo-cap", "amount": 20000 } }, "is_enabled": true, "payment_gate_config": { "payment_gate_type": "STRIPE", "stripe_config": { "payment_type": "INVOICE" } }, "threshold_amount": 500, "recharge_to_amount": 2000 } }' ``` For this contract, we have a spend tracker that is scoped to include discounted manual and threshold billing commits. The `discount_config` on the `prepaid_balance_threshold_configuration` points at this spend tracker to enforce a cap. When the cap is reached, new threshold commits will not be discounted until the start of the next billing period. ## Get spend tracker total Once set up, you can query the contract to return the current spend counted towards the tracker within the current period. See an example below: ```bash theme={null} curl https://api.metronome.com/v2/contracts/get \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "data": { "id": "d7abd0cd-4ae9-4db7-8676-e986a4ebd8dc", "customer_id": "13117714-3f05-48e5-a6e9-a66093f13b4d", ... "spend_trackers": [ { "alias": "promo-cap", "credit_type_id": "usd_credit_type_id", "reset_frequency": "BILLING_PERIOD", "accumulated_spend": { "amount": 14253.22, "period_starting_at": "2026-05-01T00:00:00.000Z", "period_ending_before": "2026-06-01T00:00:00.000Z" }, "applicable_spend_specifiers": [ { "spend_type": "COMMIT_PURCHASE", "sources": ["THRESHOLD_RECHARGE", "MANUAL"], "discounted": "DISCOUNTED_ONLY" } ] } ] } }' ``` While spend trackers can be used to dynamically trigger certain configurations, like the threshold billing discount config shown above, users can leverage this spend tracker to enforce internal pricing schemes. For example, if you wanted to enforce a spend cap for [payment gated commits](/guides/pricing-packaging/apply-credits-and-commits/manual-payment-gated-commits), you could check the spend tracker before issuing the commit to enforce a cap. # Let customers manage spend and usage Source: https://docs.metronome.com/guides/customers-billing/optimize-customer-experience/customer-controls Transparency is crucial in usage-based pricing. Enabling customers to monitor and manage their usage in real time builds trust and encourages product adoption. Metronome provides the data and real-time control necessary to implement flexible and customizable billing functionality directly in your product. Using threshold notifications, you can give your customers the power to proactively manage spend limits, commit balances, and invoice totals. Metronome evaluates threshold notifications as usage events are processed, triggering alarm states when a threshold is reached. The notifications are sent to your application through a preconfigured webhook, allowing you to take action as soon as the alarm state triggers as part of your entitlement management workflows. To learn more about supported notification types and behavior, see [Create and manage notifications](/guides/customers-billing/set-up-notifications/create-and-manage-notifications). ## Enable custom spend limits​ Spend limits provide an important safety mechanism to reassure customers that their total costs won't exceed a predefined threshold. These limits trigger notifications and prevent further service usage in the case of a hard limit. Implement spend limits with the following workflow: 1. An end user sets limits in your application (see example UI below) 2. Using the Metronome API, your application creates a `spend_threshold_reached` notification for each limit with a threshold matching the values entered by the end user 3. Metronome continuously evaluates the spend for the billing period, setting the notification to an `in_alarm` state once the threshold is reached 4. Metronome sends a notification to a webhook configured for your application that you can use to notify your customer and optionally block access to the service Set spend limits The following API calls show how to set notifications in Metronome based on a spend threshold, enabling you to support your end users’ ability to set soft and hard limits. Each response returns the ID of the created threshold notification. Save these to a table to make them easily available when a user wants to update their soft and hard spend limits. ```bash theme={null} curl https://api.metronome.com/v1/alerts/create \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "alert_type": "spend_threshold_reached", "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "name": "SOFT spend threshold", "threshold": 5000, "customer_id": "75077603-26d4-45c0-a4b7-97b082ccc5f9" }' curl https://api.metronome.com/v1/alerts/create \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "alert_type": "spend_threshold_reached", "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "name": "HARD spend threshold", "threshold": 10000, "customer_id": "75077603-26d4-45c0-a4b7-97b082ccc5f9" }' ``` **INFO** The `credit_type_id` of `2714e483-4ff1-48e4-9e25-ac732e8f24f2` represents USD, where values are in **cents** (for example, a `threshold` of `10000` = \$100.00). Other supported currencies use whole units. See [currency denomination](/guides/pricing-packaging/make-pricing-changes/use-currency-custompricingunits#currency-denomination) for details. Spend notifications are not limited to USD — you can set them in custom pricing units, which you can define on the **Offering** page in the [Metronome app](https://app.metronome.com/offering/pricing-units/custom-pricing-units). ### Process notifications sent through a webhook​ Taking action on notifications in real time requires the use of webhooks—dedicated endpoints in your application for receiving and processing notifications. Configure webhooks in Metronome in under [Developer - Notifications - Webhooks](https://app.metronome.com/developer/notifications/webhooks). When a notification triggers in Metronome, a POST request is sent to your webhook with basic information related to the notification, including the type, customer ID, and alert ID. Upon receiving a webhook notification, your application can process it and take the appropriate action. Learn more best practices around handling [webhook notifications](/guides/platform-configuration/setup-webhooks). For the spend limit example above, processing the webhook payload might look like this: 1. Check that the alert ID matches a threshold notification you have configured and that the customer ID matches the one you associated with the alert ID. 2. Using information included in the webhook like alert ID, name, and threshold, determine whether the customer exceeded their soft limit, or their hard limit. 3. If the customer exceeded their soft limit, notify the customer inside the app, through email, or via your preferred delivery mechanism. 4. If the customer exceeded their hard limit, disable the customer’s access to your services to prevent any additional spend. Inform the customer they have reached their hard spend limit and prompt them to update their limits in your application if they’d like to continue using the service. 5. For any limits that have changed, archive the previous notifications before creating new notifications with the updated thresholds: ```bash theme={null} curl https://api.metronome.com/v1/alerts/archive \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "id": "e9c0d89d-040e-4ffc-91f6-001c6954d7a7" }' ``` In addition to using webhook notifications, you can regularly check the status of customer notifications at any time that makes sense in the customer workflow, such as upon initial login. Do this with calls to the [/customer-alerts/get](/api-reference/alerts/get-an-alert) endpoint for a specific threshold notification, or the [/customer-alerts/list](/api-reference/alerts/list-customer-alerts) endpoint for all threshold notifications. ### Enable custom spend limits for a specific dimension​ Your customers may want the flexibility to set up custom spend limits for a subset of usage. For example, they may want to receive a notification or limit access when a specific `user_id` has spent more than \$500 in a billing period, or when any `organization_id` has spent more than \$5000. In Metronome, you have the option of adding `group_values` filters to spend threshold notifications to support this use case. Create a notification on spend for `user_id` = `user_123` using the following API call: ```bash theme={null} curl https://api.metronome.com/v1/alerts/create \ -d '{ "alert_type": "spend_threshold_reached", "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "name": "$500 spend limit for user_123", "threshold": 50000, "customer_id": "5cceec38-51fe-4399-8bed-fcb2a8ad1fb7", "group_values":[{"key":"user_id", "value":"user_123"}] }' ``` Create a threshold notification on spend for any `organization_id` using the following API call. If any `organization_id` spends more than \$5000, you will receive a webhook notification, including which `organization_id` breached the threshold in the payload. ```bash theme={null} curl https://api.metronome.com/v1/alerts/create \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "alert_type": "spend_threshold_reached", "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "name": "$5000 spend limit for any organization", "threshold": 500000, "customer_id": "5cceec38-51fe-4399-8bed-fcb2a8ad1fb7", "group_values":[{"key":"organization_id"}] }' ``` To retrieve an customer threshold notification for any `organization_id` (e.g. `finance`), use the [/customer-alerts/get](/api-reference/alerts/get-an-alert) endpoint. ```bash theme={null} curl https://api.metronome.com/v1/customer-alerts/get \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "5cceec38-51fe-4399-8bed-fcb2a8ad1fb7", "alert_id": "e9c0d89d-040e-4ffc-91f6-001c6954d7a7" "group_values": [{"key":"organization_id", "value":"finance"}] }' ``` In order to use a key in the `group_values` field, make sure that key is added as a [group key](/guides/get-started/core-concepts/create-billable-metrics#3-define-group-keys) on billable metrics associated with that customer's contract. Spend on products where the key is not a group key on the underlying billable metrics will not contribute to the threshold. When evaluating spend threshold notifications for a specific dimension, Metronome recomputes the invoice as if the group key is a presentation group key. In cases with tiered pricing, quantity rounding, or MAX billable metrics, the pricing and packaging will be applied to the subset of usage you define. For example, if you create a threshold notification for `organization_id` = `finance`, the quantity will be rounded for the subset of usage by the finance org. INFO For a given customer, you can set spend threshold notifications for three keys. For example, you can set spend threshold notifications for a `user_id`, a `project_id`, and an `organization_id`, but will be prevented from adding a notification using a fourth key. For keys with more than 5000 values for a given customer, contact us via the [Metronome support portal](https://support.metronome.com/) to discuss your spend threshold notification configuration. ## Monitor commit balance​ Another useful scenario for flexible notification management is helping customers monitor the balance related to a contractually established spend commit. This example assumes you have set up products, rates, contracts, and commits in Metronome and want to allow a customer to specify a commitment balance at which they want to receive a notification. See the following call below: ```bash theme={null} curl https://api.metronome.com/v1/alerts/create \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "alert_type": "low_remaining_commit_balance_reached", "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "name": "Commitment Balance Alert", "threshold": 500, "customer_id": "5cceec38-51fe-4399-8bed-fcb2a8ad1fb7" }' ``` This gives you an opportunity to notify your customer that they’re reaching the end of their commit, or even send a message to your sales team to contact this customer for a potential renegotiation. It also provides a trigger for cutting off access if appropriate when the commit balance reaches zero. ## Enable custom invoice total limits​ The [spend threshold reached](/guides/customers-billing/set-up-notifications/create-and-manage-notifications#spend-alerts) notification described above uses a customer's usage-based spend prior to credit and commit drawdown. You can also set notifications on invoice total. The invoice total is evaluated after credit and commit drawdown and corresponds to the amount a customer will pay. To allow a customer to specify an invoice total reached threshold notification on usage invoices, see the following call: ```bash theme={null} curl https://api.metronome.com/v1/alerts/create \ -H "Authorization: Bearer bb842ce6470ef5fc9982b861b53c0b7c3c111ac34b7980b38b70c095e77de2c4" \ -H "Content-Type: application/json" \ -d '{ "alert_type": "invoice_total_reached", "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "name": "$100 usage invoice total reached alert", "threshold": 10000, "customer_id": "5cceec38-51fe-4399-8bed-fcb2a8ad1fb7", "invoice_types_filter": ["USAGE"] }' ``` # Build API-powered customer dashboards Source: https://docs.metronome.com/guides/customers-billing/optimize-customer-experience/customer-dashboards-and-reporting This use case walks through examples for how to build an API-powered customer dashboard. Metronome integrates with your core product by providing cost visibility to end customers. This helps them optimize usage patterns and derive maximum value from your product. With your usage-based offerings, customers expect transparency into their consumption and associated costs. Metronome's APIs and data export features integrate with your product, enabling you to create end-user dashboards that provide this critical visibility. ## Interactive demo Explore a fully working reference dashboard built on the Metronome API. This example dashboard shows how you can display usage tracking, credit balance management, invoice history, and self-serve controls, powered by the same endpoints documented below. Open demo dashboard → ## Show customers data they want to see Customer dashboards provide essential insights into resource consumption and cost management: a critical customer interface with your product. Customers want to understand their usage patterns so they can make informed decisions around their usage and build trust that they're getting metered accurately. Excellent customer dashboards that delight customers often share similar characteristics: * **Granular usage visibility** Customers want to decompose their usage by product or feature to better understand their biggest cost centers and reallocate usage when needed. * **Up-to-date spend visibility** Customers want to see how much in spend they’ve already accumulated for their current billing period before getting charged, preventing surprises at the end of the billing period. * **Commitment tracking** Customers want to know the available balance for their current commits to plan their usage and proactively purchase new commits. * **Build trust** Customers expect high precision in metering their usage. Providing transparency into the rating process in real time builds confidence that this expectation is met. You can accomplish all of the above outcomes for your customer dashboards by building directly off of the Metronome API. Metronome also provides out-of-the-box embeddable dashboards that show a customer's usage and invoices. ## Use Metronome APIs to power customer-facing dashboards Metronome offers several API endpoints that provide data useful for powering dashboards that your customers want to see. This section explores a few of these endpoints. For assistance in designing your customer dashboard with Metronome APIs, contact us via the [Metronome support portal](https://support.metronome.com/). ### Backend integration pattern best practice When integrating Metronome data into your application to expose to your end users, you must ensure that all Metronome APIs get called from one of your backend services to return data to your frontend application. Implement all authentication against Metronome using a securely stored [token](/api-reference/authorization) available to your backend service. Never expose Metronome API tokens to users or use them on frontend clients. ``` Your Frontend App <--> Your Backend Service <--> Metronome APIs ``` ### Display granular usage visibility One way to enhance your customer's experience is to provide them with visibility of their usage in real-time. Metronome can slice and filter this usage based on any of your event properties, enabling highly granular analysis. This transparency enables them to derive insights into their usage patterns, previously unknown to them, and take action. For example, by viewing their usage mid-month, a customer might realize that certain servers they spun up consume a disproportionately greater amount of memory than in previous months. This insight enables them to assess their own internal processes and identify potential optimizations. To explore how you can create this, consider the following example: create a bar chart that filters down to usage of a particular metric over time. Display granular usage visibility The Metronome [usage endpoint](/api-reference/usage/get-batched-usage-data) provides the foundation for showing users visibility into usage from each of their billable metrics over time. For example, this request shows daily usage from the `CPU hours` billable metric over the month of October 2024, broken out by region: ```bash theme={null} curl https://api.metronome.com/v1/usage \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "140a7113-76c4-4ce2-9379-29fa3375d23c", "billable_metric_id": "f3b17844-a98d-413a-b310-5be1df72213d", "starting_on": "2024-10-01T00:00:00Z", "ending_before": "2024-11-01T00:00:00Z", "window_size": "day", "group_by": { "key": "region" } }' ``` An example response to this request looks like: ```json theme={null} { "data": [ { "value": 37, "group_key": "region", "group_value": "ap-south-1", "starting_on": "2024-10-01T00:00:00+00:00", "ending_before": "2024-10-02T00:00:00+00:00" }, { "value": 24, "group_key": "region", "group_value": "us-east-1", "starting_on": "2024-10-01T00:00:00+00:00", "ending_before": "2024-10-02T00:00:00+00:00" }, { "value": 12, "group_key": "region", "group_value": "us-east-2", "starting_on": "2024-10-01T00:00:00+00:00", "ending_before": "2024-10-02T00:00:00+00:00" }, { "value": 91, "group_key": "region", "group_value": "ap-south-1", "starting_on": "2024-10-02T00:00:00+00:00", "ending_before": "2024-10-03T00:00:00+00:00" } ], "next_page": null } ``` Use this pseudocode to pull together data from the Metronome usage endpoint in your backend and present it to users as a stacked bar chart in your frontend. ```python Backend theme={null} # Step 1: Extract the data from the API response data = metronome_api_response['data'] # Step 2: Create a dictionary to store the processed data processed_data = {} # Step 3: Iterate through the data and organize it by date and region for item in data: date = item['starting_on'] region = item['group_value'] value = item['value'] if date not in processed_data: processed_data[date] = {} processed_data[date][region] = value # Step 4: Create a list of unique regions and sort them regions = sorted(set(item['group_value'] for item in data)) # Step 5: Prepare the data for charting chart_data = [] for date in sorted(processed_data.keys()): data_point = {'date': date} cumulative_value = 0 for region in regions: value = processed_data[date].get(region, 0) data_point[f"{region}_start"] = cumulative_value cumulative_value += value data_point[f"{region}_end"] = cumulative_value chart_data.append(data_point) # Return chart data for frontend chart library usage return chart_data ``` ```javascript Frontend theme={null} # Step 1: Fetch billable metric chart data from your backend (from above) chart_data = fetch_from_backend('/api/customer_usage/:customer_id') # Step 2: Use the chart_data to create your stacked bar chart # The exact implementation depends on your charting library # Example using a hypothetical charting library: create_stacked_bar_chart( data=chart_data, x_axis='date', y_axis='value', stacks=regions, colors=['blue', 'red', 'green'], # Assign colors to each region title='Usage by Region Over Time' ) ``` ### Display commitment tracking Inside of Metronome, you can view a ledger of each commit and credit. This offers visibility into current balance and the events that contributed to it. You can imagine that your end customers would also benefit from this visibility to understand their remaining balance on a specific credit or commit. This can help inform their decision-making, such as purchasing a new commit or throttling their usage to stay within their remaining allotment. This example table shows how you could display this information to your customer: Commitment tracking Use the Metronome [`/listBalances`](/api-reference/credits-and-commits/list-balances) endpoint to understand the current state of a customer's balance across commits and credits. For example, consider a customer that has: * Received a prepaid commit of \$100, starting on September 1st, 2024. * Received a free reward credit for \$5, starting on October 1st, 2024. The free credit should be used in full before the remaining prepaid commit gets burned down. * Spent \$65 in the month of September. * Spent \$20 in the month of October. In this scenario, the customer has the following balances remaining: * Reward credit: \$0 remaining, \$5 used * Prepaid commit: \$20 remaining, \$80 used * Overall balance: \$20 remaining, \$85 used Use the `/listBalances` endpoint to retrieve information about the prepaid commit and bonus credit from September 1st onward in one response. Because the request includes the `include_balance: true` parameter, for each commit or credit a `balance` field returns that reflects the amount of commit or credit available to use now. Note that any upcoming, not-yet-started commit or credit segments are not included in this balance as they are not available to use. ```bash theme={null} curl -X POST https://api.metronome.com/v1/contracts/customerBalances/list \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "23f894af-c350-45df-bb3e-3b134e352109", "include_ledgers": true, "include_balance": true, "starting_at": "2024-09-01T00:00:00Z", "include_contract_balances": true }' ``` ```json theme={null} { "data": [ { "id": "b8bc055d-2c0f-4629-b9e4-c87e0b59da1e", "contract": { "id": "8b6cb03d-c9c7-4230-9656-ed8e106bc7bd" }, "product": { "id": "d72716a4-1dcc-4e91-8ad4-a1be29c917a7", "name": "Prepaid Credits" }, "priority": 100, "applicable_contract_ids": ["8b6cb03d-c9c7-4230-9656-ed8e106bc7bd"], "access_schedule": { "credit_type": { "id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "name": "USD (cents)" }, "schedule_items": [ { "id": "e20d07a1-63c0-4fef-ac23-50f7b710cf3e", "amount": 10000, "starting_at": "2024-09-01T00:00:00+00:00", "ending_before": "2025-09-01T00:00:00+00:00" } ] }, "balance": 2000, "ledger": [ { "amount": 10000, "timestamp": "2024-09-01T00:00:00+00:00", "segment_id": "e20d07a1-63c0-4fef-ac23-50f7b710cf3e", "type": "PREPAID_COMMIT_SEGMENT_START" }, { "amount": -6500, "timestamp": "2024-10-01T00:00:00+00:00", "segment_id": "e20d07a1-63c0-4fef-ac23-50f7b710cf3e", "type": "PREPAID_COMMIT_AUTOMATED_INVOICE_DEDUCTION", "invoice_id": "3f13f349-c1a6-5e98-81ce-fd3743904e6f" }, { "amount": -1500, "timestamp": "2024-11-01T00:00:00+00:00", "segment_id": "e20d07a1-63c0-4fef-ac23-50f7b710cf3e", "type": "PREPAID_COMMIT_AUTOMATED_INVOICE_DEDUCTION", "invoice_id": "832ed401-17ed-56dd-87c4-b5684a52b26c" } ], "custom_fields": {}, "type": "PREPAID", "invoice_schedule": { "credit_type": { "id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "name": "USD (cents)" }, "schedule_items": [ { "id": "a528d105-4a7c-4a93-b630-56ccf8a675d5", "invoice_id": "0267436e-3c4d-5ee4-9369-5618f27229a5", "amount": 10000, "unit_price": 10000, "quantity": 1, "timestamp": "2024-09-01T00:00:00+00:00" } ] } }, { "id": "c0522458-353f-4a39-bad2-a315ff2eed88", "contract": { "id": "8b6cb03d-c9c7-4230-9656-ed8e106bc7bd" }, "product": { "id": "aa52ce3b-f896-4f5c-b1ec-a71dff8ebfeb", "name": "Reward credit" }, "priority": 1, "applicable_contract_ids": ["8b6cb03d-c9c7-4230-9656-ed8e106bc7bd"], "access_schedule": { "credit_type": { "id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "name": "USD (cents)" }, "schedule_items": [ { "id": "3b4be61d-26d0-46a5-acb5-c55d5cce0d9c", "amount": 500, "starting_at": "2024-10-01T00:00:00+00:00", "ending_before": "2024-11-01T00:00:00+00:00" } ] }, "balance": 0, "ledger": [ { "amount": 500, "timestamp": "2024-10-01T00:00:00+00:00", "segment_id": "3b4be61d-26d0-46a5-acb5-c55d5cce0d9c", "type": "CREDIT_SEGMENT_START" }, { "amount": -500, "timestamp": "2024-11-01T00:00:00+00:00", "segment_id": "3b4be61d-26d0-46a5-acb5-c55d5cce0d9c", "type": "CREDIT_AUTOMATED_INVOICE_DEDUCTION", "invoice_id": "832ed401-17ed-56dd-87c4-b5684a52b26c" } ], "custom_fields": {}, "type": "CREDIT" } ], "next_page": null } ``` Use this pseudocode to pull together the data from the Metronome `/listBalances` endpoint in your backend and present it to end users as a stacked bar chart in your frontend. ```python Backend theme={null} # Step 1: Extract the data from the Metronome API response data = metronome_api_response['data'] # Step 2: Initialize variables for overall totals total_granted = 0 total_used = 0 # Step 3: Process each grant processed_grants = [] for item in data: grant_id = item['id'] grant_type = item['type'] product_name = item['product']['name'] # Calculate total granted for this item granted = sum(schedule_item['amount'] for schedule_item in item['access_schedule']['schedule_items']) # Get remaining amount remaining = item['balance'] # Calculate used amount used = granted - remaining # Add to overall totals total_granted += granted total_used += used # Add grant info to list processed_grants.append({ 'id': grant_id, 'type': grant_type, 'product_name': product_name, 'granted': granted, 'used': used, 'remaining': remaining }) # Step 4: Calculate total remaining total_remaining = total_granted - total_used # Step 5: Prepare result result = { 'grants': processed_grants, 'total': { 'granted': total_granted, 'used': total_used, 'remaining': total_remaining } } # Step 6: Return processed data for frontend use return result ``` ```javascript Frontend theme={null} # Step 1: Fetch processed credit and commit data from backend processed_data = fetch_from_backend('/api/credit_commit_data/:customer_id') # Step 2: Display individual grants for grant in processed_data['grants']: display_grant_info(grant) # Step 3: Display overall totals display_overall_totals(processed_data['total']) ``` Additionally, you may want to show a running total of the remaining balance to your customer on a general overview page, without the ledger detail. Metronome offers an ergonomic way to pull a total remaining balance in these scenarios. For example, you may have heard feedback that customers want to understand their remaining balance on the home page of your app, without needing to click into the detailed billing view to understand their detailed commit and credit drawdowns. In this case you can make a straightforward call to the [`/getNetBalance`](https://docs.metronome.com/api-reference/credits-and-commits/get-the-net-balance-of-a-customer) endpoint. The following call would return the real-time balance without needing to parse through individual balance details. ```bash theme={null} curl -X POST https://api.metronome.com/v1/contracts/customerBalances/getNetBalance \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "23f894af-c350-45df-bb3e-3b134e352109" }' ``` ### Display up-to-date spend While the usage dashboard helps derive granular insights into usage patterns, often times this isn't the full story. Your customers also want to understand the associated costs of their usage. This helps them contextualize their analysis by understanding the potential cost savings associated with potential process or architectural changes. Additionally, it eliminates the potential of a surprise at the end of the month when they receive their invoice, which can mitigate the risk of potential disputes. To articulate a customer's cost, create a dashboard inside of your product that shows spend over time, segmented by certain properties. For example, spend by region over time: Display up-to-date spend Use the Metronome [invoice breakdown endpoint](/api-reference/invoices/list-invoice-breakdowns) to view spend over a given time window. The invoice breakdown endpoint gets returned for each line item on a customer's invoice in hourly or daily buckets. If commits or credits get consumed against certain line items during the period, they display as separate line items to mark the deductions for the amount of credits used. For example, this request generates a customer's daily spend across all line items for the month of October 2024. In this example a customer doesn't burn against any set of credits or commits and only pays in arrears. ```bash theme={null} curl https://api.metronome.com/v1/customers/d7abd0cd-4ae9-4db7-8676-e986a4ebd8dc/invoices/breakdowns?starting_on=2024-10-01T00%3A00%3A00Z&ending_before=2024-11-01T00%3A00%3A00Z&window_size=day \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" ``` ```json theme={null} { "data": [ { "id": "c5b9aab9-377b-517d-a634-924e35e7d110", "issued_at": "2024-11-02T00:00:00+00:00", "start_timestamp": "2024-10-01T00:00:00+00:00", "end_timestamp": "2024-11-01T00:00:00+00:00", "customer_id": "140a7113-76c4-4ce2-9379-29fa3375d23c", "customer_custom_fields": {}, "type": "USAGE", "credit_type": { "id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "name": "USD (cents)" }, "status": "DRAFT", "total": 7300, "external_invoice": null, "contract_id": "28d9bc16-7c56-4d4a-a2b9-b4c3ede34eeb", "contract_custom_fields": {}, "line_items": [ { "product_id": "d111fa1e-861e-48bb-82a6-3924d6cf0636", "product_type": "UsageProductListItem", "product_custom_fields": {}, "name": "My Product", "total": 3700, "credit_type": { "id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "name": "USD (cents)" }, "starting_at": "2024-10-01T00:00:00+00:00", "ending_before": "2024-11-01T00:00:00+00:00", "unit_price": 100, "quantity": 37, "presentation_group_values": { "region": "ap-south-1" } }, { "product_id": "d111fa1e-861e-48bb-82a6-3924d6cf0636", "product_type": "UsageProductListItem", "product_custom_fields": {}, "name": "My Product", "total": 2400, "credit_type": { "id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "name": "USD (cents)" }, "starting_at": "2024-10-01T00:00:00+00:00", "ending_before": "2024-11-01T00:00:00+00:00", "unit_price": 100, "quantity": 24, "presentation_group_values": { "region": "us-east-1" } }, { "product_id": "d111fa1e-861e-48bb-82a6-3924d6cf0636", "product_type": "UsageProductListItem", "product_custom_fields": {}, "name": "My Product", "total": 1200, "credit_type": { "id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "name": "USD (cents)" }, "starting_at": "2024-10-01T00:00:00+00:00", "ending_before": "2024-11-01T00:00:00+00:00", "unit_price": 100, "quantity": 12, "presentation_group_values": { "region": "us-east-2" } } ], "custom_fields": {}, "billable_status": "billable", "breakdown_start_timestamp": "2024-10-01T00:00:00.000Z", "breakdown_end_timestamp": "2024-10-02T00:00:00.000Z" } ], "next_page": null } ``` If you update the scenario above to show the customer burning down against a \$200 prepaid commit, you see the commit deductions represented in the breakdown in addition to the usage line items. Use these fields if you want to show credit and commit burndown over time. ```json theme={null} { "data": [ { "id": "5d960878-2553-5290-bddd-8def5f42532a", "issued_at": "2024-11-02T00:00:00+00:00", "start_timestamp": "2024-10-01T00:00:00+00:00", "end_timestamp": "2024-11-01T00:00:00+00:00", "customer_id": "140a7113-76c4-4ce2-9379-29fa3375d23c", "customer_custom_fields": {}, "type": "USAGE", "credit_type": { "id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "name": "USD (cents)" }, "status": "DRAFT", "total": 0, "external_invoice": null, "contract_id": "95a390e3-b5c6-4264-8c7a-3583ec574c42", "contract_custom_fields": {}, "line_items": [ { "product_id": "d111fa1e-861e-48bb-82a6-3924d6cf0636", "product_type": "UsageProductListItem", "product_custom_fields": {}, "name": "My Product", "total": 3700, "credit_type": { "id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "name": "USD (cents)" }, "starting_at": "2024-10-01T00:00:00+00:00", "ending_before": "2024-11-01T00:00:00+00:00", "commit_id": "f3243ab9-dd22-4a6e-b4c3-7b2a0f8e8732", "commit_segment_id": "ede54bc6-0c23-4d0b-a096-d6c79f38ff31", "commit_type": "PrepaidCommit", "commit_custom_fields": {}, "unit_price": 100, "quantity": 37, "presentation_group_values": { "region": "ap-south-1" } }, { "product_id": "d111fa1e-861e-48bb-82a6-3924d6cf0636", "product_type": "UsageProductListItem", "product_custom_fields": {}, "name": "Prepaid Credits applied", "total": -3700, "credit_type": { "id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "name": "USD (cents)" }, "starting_at": "2024-10-01T00:00:00+00:00", "ending_before": "2024-11-01T00:00:00+00:00", "commit_id": "f3243ab9-dd22-4a6e-b4c3-7b2a0f8e8732", "commit_segment_id": "ede54bc6-0c23-4d0b-a096-d6c79f38ff31", "commit_type": "PrepaidCommit", "commit_custom_fields": {} } ], "custom_fields": {}, "billable_status": "billable", "breakdown_start_timestamp": "2024-10-01T00:00:00.000Z", "breakdown_end_timestamp": "2024-10-02T00:00:00.000Z" } ], "next_page": null } ``` Use this pseudocode to pull together data from the Metronome invoice breakdown endpoint in your backend and present it to users as a stacked bar chart in your frontend. ```python Backend theme={null} # Step 1: Extract the data from the Metronome API response data = metronome_api_response['data'] # Step 2: Create a dictionary to store the processed data processed_data = {} # Step 3: Iterate through the data and organize it by date and region for item in data: date = item['breakdown_start_timestamp'] for line_item in item['line_items']: region = line_item['presentation_group_values']['region'] value = line_item['total'] / 100 # Convert cents to dollars if date not in processed_data: processed_data[date] = {} if region not in processed_data[date]: processed_data[date][region] = 0 processed_data[date][region] += value # Step 4: Create a list of unique regions and sort them regions = sorted(set(region for date_data in processed_data.values() for region in date_data.keys())) # Step 5: Prepare the data for charting chart_data = [] for date in sorted(processed_data.keys()): data_point = {'date': date} for region in regions: data_point[region] = processed_data[date].get(region, 0) chart_data.append(data_point) # Return chart data for frontend chart library usage return chart_data ``` ```javascript Frontend theme={null} # Step 1: Fetch spend over time chart data from your backend chart_data = fetch_from_backend('/api/customer_spend/:customer_id') # Step 2: Extract unique regions from the chart data regions = list(set(key.split('_')[0] for key in chart_data[0].keys() if key.endswith('_start'))) # Step 3: Use the chart_data to create your stacked bar chart # The exact implementation depends on your charting library # Example using Chart.js: create_stacked_bar_chart( data=chart_data, x_axis='date', y_axis='Spend (USD)', stacks=regions, colors=['#4e79a7', '#f28e2c', '#e15759'], # Assign colors to each region title='Spend by Region Over Time' ) ``` ## Embeddable dashboards Share Metronome invoices and usage data with your customers through customizable embeddable dashboards. ### Invoice Dashboard The invoice dashboard allows your customers to view their current and historical invoices (draft, finalized, and voided), up to 90 days old. Invoice dashboard screenshot Filter the invoices returned using the `dashboard_options` array, which has the following optional parameters: * `show_zero_usage_line_items`: Configure whether line items with zero quantity are shown on the invoice. Defaults to false. * `contract_id`: For customers with multiple contracts, display only the invoices on a specific contract. Defaults to all. * `invoice_type`: Display invoices by type to show only usage invoices or only scheduled (subscription, commit purchase, or scheduled charge invoices). Defaults to all. * `invoice_status_filter`: Display invoices by status ("VOID", "FINALIZED", "DRAFT", "FINALIZED\_AND\_DRAFT", or "ALL"). Defaults to all. ### Usage dashboard The usage dashboard shows usage metrics attached to a customer's current contract for the past 30, 60, or 90 days. Usage dashboard screenshot ### Commits and credits dashboard The commits and credits dashboard allows your customers to view their current and historical commit and credit grants, including: * Remaining and historical balances * Grant and deduction history * Access schedules and expiration dates Commits and credits dashboard screenshot ### Embed a dashboard Use the Metronome API to retrieve an embeddable dashboard URL which can be displayed through an iframe within your internal billing UI. 1. Create an [API token](/api-reference/authorization) (if you don't already have one) 2. Use the [`/dashboards/getEmbeddableUrl`](/api-reference/customers/get-an-embeddable-customer-dashboard) endpoint to pass the `customer_id` and specify the dashboard you want to display. ### Override the color palette The `/dashboards/getEmbeddableUrl` endpoint supports a `color_overrides` array to override the color palette and match your design. See the full [list of colors](/api-reference/customers/get-an-embeddable-customer-dashboard). The image demonstrates where Metronome uses each named color. For example, `gray_dark` applies to standard text; `primary_medium` applies to selected text. Dashboard style guide for invoice dashboard # Track the remaining balance of a credit or commit Source: https://docs.metronome.com/guides/customers-billing/optimize-customer-experience/get-remaining-balance Tracking the remaining balance of credits and commits helps you accurately understand account health, forecast revenue, and track assets and liabilities. It also supports providing customers with up-to-date information on their remaining balance. There are many ways to display remaining balance to customers and Metronome provides the flexibility to display both aggregated and detailed views. Balance values can be **fractional numbers** (e.g., `0.8` cents for USD). When integrating with the balances API, do not truncate balances to integers — doing so may cause data loss. Rounding is acceptable if done intentionally. For USD, amounts are denominated in cents, so a balance of `0.8` represents \$0.008. ## Fetch the total remaining balance on a customer To display an aggregated real-time balance to your customers, call the [`/getNetBalance`](https://docs.metronome.com/api-reference/credits-and-commits/get-the-net-balance-of-a-customer) endpoint. This endpoint returns a single aggregated sum of the remaining balance on a customer, with advanced filtering by balance type, currency, pending charges, and custom fields. ## Build a detailed ledger view of individual balances Metronome also supports more detailed views of individual balances by tracking ledger entries using the [`listBalances`](https://docs.metronome.com/api-reference/credits-and-commits/list-balances) endpoint. Each credit or commit is associated with a ledger, which records events that change the balance of the commit or credit. Adding all of the entries in a ledger results in the total remaining balance associated with that ledger. For example, there are ledger entries associated with the `access_schedule` beginning, invoice deductions (drawdowns of the credit or commit corresponding to usage), and expirations. Each ledger entry is associated with a `type`, an `amount` (which can be positive or negative), and an effective `timestamp`. There is one invoice deduction ledger entry for each invoice that consumes a credit or commit. The `timestamp` associated with invoice deduction ledger entries is always the end of the service period associated with the usage invoice. Use the `timestamp` to show customers their remaining balance including pending charges, or excluding pending charges. ### Example ledger Consider an example where a customer is issued a \$100 credit with one access segment from September 01, 2024 through October 01, 2024. During the month of September, the customer consumed \$63 of the credit. The remaining credit balance expired after October 01. As a result, this credit has three ledger entries:
Type Timestamp Amount
credit\_segment\_start 9/1/2024 +\$100
credit\_automated\_invoice\_deduction 10/1/2024 -\$63
credit\_segment\_expiration 10/1/2024 -\$37
### Manual ledger entries You may want to adjust a credit or commit's ledger to account for mistakes, migrate existing customers with outstanding balances to Metronome, or many other reasons. Apply positive or negative adjustments to a credit or commit's ledger through the [Metronome app](https://app.metronome.com/) or API using the [`/addManualBalanceLedgerEntry`](/api-reference/credits-and-commits/add-a-manual-balance-entry) endpoint. ### Credit ledger entry types
Type Description
credit\_segment\_start Represents that a credit segment started and the customer now has access to the usage amount for that segment. The access schedule of the credit describes these segments.
credit\_automated\_invoice\_deduction Represents deductions from the credit segment caused by a usage invoice that included usage applicable to this credit.
credit\_segment\_expiration Represents the unused credit amount that expired at the end of a credit segment.
credit\_manual Represents a manual ledger entry added to a credit.
credit\_seat\_based\_adjustment Represents the additional credit associated with a seat increment when using recurring credits linked to a subscription
### Commit ledger entry types
Type Description
postpaid\_initial\_balance Represents the starting balance of a postpaid commit.
postpaid\_automated\_invoice\_deduction Represents deductions from the remaining obligation of the postpaid commit as the result of an invoice with usage that applies to this commit.
postpaid\_trueup Represents a true-up invoice issued for this commit to cover usage not covered by automated usage invoices.
postpaid\_rollover Represents unused usage from the postpaid commit which was rolled over to a new contract.
postpaid\_manual Represents a manual ledger entry added to a postpaid commit.
postpaid\_commit\_expiration Represents commit amount unused and expired at the end of a commit segment. Does not include usage that rolled over to a new contract.
prepaid\_segment\_start Represents that a prepaid commit segment started and the customer now has access to the usage amount for that segment. The access schedule of the prepaid commit describes these segments.
prepaid\_automated\_invoice\_deduction Represents deductions from the prepaid commit segment caused by a usage invoice that included usage applicable to this commit.
prepaid\_rollover Represents unused usage from the prepaid commit that rolled over to a new contract.
prepaid\_segment\_expiration Represents commit amount unused and expired at the end of a commit segment. Does not include usage that rolled over to a new contract.
prepaid\_commit\_expiration Represents commit amount unused and expired at the end of a commit segment. Does not include usage that rolled over to a new contract.
prepaid\_manual Represents a manual ledger entry added to a prepaid commit.
prepaid\_commit\_seat\_based\_adjustment Represents the additional commit associated with a seat increment when using recurring commits linked to a subscription
# India e-mandate support for Stripe invoices Source: https://docs.metronome.com/guides/customers-billing/optimize-customer-experience/india-e-mandates Invoice Indian credit cards using RBI-compliant Stripe mandates. In accordance with RBI pre-authorization requirements, this feature enables you to charge customers with Indian credit cards using Stripe mandates. After a mandate is active, Metronome will use it for eligible off-session charges. ## Setup ### 1. Collect the customer's payment method and create the mandate via SetupIntent When collecting the user's card on-session, create a mandate using a Stripe `SetupIntent`. The user completes authentication during confirmation, and Stripe creates the mandate for that payment method. ```bash theme={null} curl https://api.stripe.com/v1/setup_intents \ -u sk_test_...: \ -d customer=cus_123 \ -d payment_method=pm_123 \ -d confirm=true \ -d "payment_method_options[card][mandate_options][amount_type]"=maximum \ -d "payment_method_options[card][mandate_options][amount]"=500000 \ -d "payment_method_options[card][mandate_options][currency]"=inr \ -d "payment_method_options[card][mandate_options][interval]"=sporadic \ -d "payment_method_options[card][mandate_options][reference]"=AUTO_RECHARGE_123 \ -d "payment_method_options[card][mandate_options][start_date]"=1735689600 ``` **For threshold billing customers:** * Set `interval` to `sporadic` — recharges are triggered by a balance threshold, not a fixed cadence. * Set `amount_type` to `maximum` - support varying charge amounts. * Set `amount` to a sufficiently high value - account for variance in recharge amounts over time. **For subscriptions and recurring fees (e.g. monthly PayGo):** * Set `interval` to the corresponding recurrence (e.g. `month`). * Set `amount_type` to `fixed` if the recurring fee is known, or `maximum` if it is variable. * Set `amount` to the known recurring fee or a sufficiently high maximum. ### 2. Wait for the mandate to become active A mandate may remain in `pending` for up to 30 minutes after creation. You can check readiness in two ways: * Listen to the `mandate.updated` webhook from Stripe and wait until `status` becomes `active`. * Retrieve the mandate by ID from the `SetupIntent` and poll until it is `active`. If the mandate transitions to `inactive`, it cannot be used. The customer will need to authorize a new mandate. ### 3. Create and map the mandate custom field On the Metronome contract, create a custom field (e.g. `stripe_mandate_id`). Via the entity mapping UI, map this contract custom field to the Stripe `invoice.payment_settings` → `default_mandate` field. ### 4. Provision the customer in Metronome Create the Metronome contract. Populate the `stripe_mandate_id` custom field with the mandate ID created in step 1. All invoices sent to Stripe will attempt to attach this mandate. ### 5. Listen for the `action_required` webhook After the invoice is created with the associated mandate, the `paymentIntent` may transition to an `action_required` state. Stripe will issue a [`invoice.payment_action_required` webhook](https://docs.stripe.com/api/events/types#event_types-invoice.payment_action_required). ### 6. Confirm payment * If the customer approves the charge, the payment succeeds and the balance is released. * If the customer does not respond or the mandate becomes inactive, the payment fails and enters the normal failure workflow. A new mandate must be collected and activated before future recharge attempts can succeed. ## Limitations * Mandates must be created and managed entirely in Stripe. Metronome does not expose an API for interacting with mandates other than returning the set custom field value. * Mandates must be set up via a `SetupIntent` since all charges, including the first one, are off-session. * Metronome does not manage mandate lifecycle events. Payment failures are surfaced through the normal webhook and failure path. It is your responsibility to update the mandate in Stripe and take appropriate action before retrying. ## Relevant documentation * [Stripe guide for RBI e-mandates](https://docs.stripe.com/india-recurring-payments) # Set prepaid balance thresholds Source: https://docs.metronome.com/guides/customers-billing/optimize-customer-experience/prepaid-balance-thresholds Use *prepaid balance threshold billing* to enable a prepaid credit model for your products. This billing model requires customers to pay for usage ahead of using the product and to maintain a positive balance to continue accessing the product. Prepaid credits are modeled as [commits](/guides/pricing-packaging/apply-credits-and-commits/create-a-pre-paid-commit) in Metronome. Prepaid balance thresholds work with both fiat currencies (such as USD) and [custom pricing units](/guides/pricing-packaging/make-pricing-changes/use-currency-custompricingunits) (such as tokens or credits). This means you can configure auto recharge for customers whose balances are denominated in custom pricing units, not just fiat currency. Prepaid balance thresholds enable: * **Auto recharge:** Automatically recharge a customer's balance when it drops to the `threshold_amount` * **Manual purchase:** [Manually purchase commits](/guides/pricing-packaging/billing-model-guides/enterprise-commit/) for customers who don't want to enable auto recharge * **Payment gating:** Gate the release of the commit balance, from an auto recharge or a manual purchase, based on successful collection of payment ## Set up auto recharge with balance thresholds Configuring auto recharge of the customer's balance on a contract ensures they never lose access to the product. ### Create a contract with balance thresholds When you [create a contract](/api-reference/contracts/create-a-contract/) in Metronome, you can optionally configure a `prepaid_balance_threshold_configuration`. This config dictates: * The `threshold_amount` for the customer's contract: the balance level when a customer is recharged. * **Note:** When evaluating whether the `threshold_amount` has been reached, Metronome considers the total balance of all contract- and customer-level commits and credits. [Individual seat-scoped credits](https://docs.metronome.com/guides/pricing-packaging/subscription/provision-your-customer#individual-seat-credit) are not included in this calculation. * The `recharge_to_amount`: the balance the customer is topped up to after a recharge initiates. * A `payment_gate_config`: configure whether to gate the release of balance on payment and what gateway to use. * Select `EXTERNAL` if you use a gateway that Metronome doesn't currently support. * If using Stripe, configure `PAYMENT_TYPE` to dictate whether payment is sent as an invoice through Stripe Billing or directly as a `paymentIntent` to Stripe's payment gateway. * If using Stripe, select your existing tax provider. * If the config `is_enabled`. If a payment fails and payment gating is enabled, this shifts to `false`. **CONFIGURE BILLING** If using Stripe as your payment gateway, ensure there's a valid Stripe billing configuration set on the contract. Additionally, set `is_enabled` to `true` if you want Metronome to immediately evaluate the contract after its creation. Additionally, users can optionally configure a `discount_config` on the `prepaid_balance_threshold_configuration`. This will discount the amount invoiced to the customer based on a percentage, where the invoice amount will be X% discounted from the access amount granted: * `fraction`: the discount applied to the invoice amount, represented as a fraction * `cap`: optionally the cap the discounted purchases up to an `amount`. The amount is tracked via a [spend tracker](/guides/customers-billing/manage-customers/spend-trackers). Once the accumulated spend hits this cap, new recharges will not be discounted for the remainder of the period defined in the spend tracker. **DISCOUNTS WITH CPUS** When using Threshold Billing with CPUs, the invoice schedule amount is calculated via the overage rate. For example, if the conversion rate between AI credits and USD was 2:1, then a recharge for 100 AI credits will cost 50 USD. If there was a discount of 10% set on the config, the 100 AI credits would now cost 45 USD. Create contracts with prepaid balance thresholds in the [Metronome app](https://app.metronome.com/) or using the [Metronome API](/api-reference/contracts/create-a-contract). ```json theme={null} { "customer_id": "6352d562-213f-4a6e-819f-58fdabc3f2b9", "rate_card_id": "a7bc3775-b651-46b6-b7e4-d225a7e55c4c", "starting_at": "2025-05-01T00:00:00.000Z", "billing_provider_configuration": { "billing_provider_configuration_id": "0d40d6ef-6a79-45c2-a716-13eed27a9c8d" }, "prepaid_balance_threshold_configuration": { "commit": { "product_id": "d6be3bf4-1669-40c9-a8b1-388bb167ab16", "name": "prepaid_commit", "description": "hello_its_me_im_in_california_dreaming" }, "is_enabled": true, "payment_gate_config": { "payment_gate_type": "STRIPE", "stripe_config": { "payment_type": "PAYMENT_INTENT" } }, "threshold_amount": 500, "recharge_to_amount": 2100, "discount_config": { "fraction": 0.9 } } } ``` **RECHARGE MINIMUMS** When setting up Auto Recharge, the `recharge_threshold` has a minimum value of \$5, and the `recharge_to amount` must always be at least \$10 higher than your threshold. For example, if your threshold is \$10, your `recharge_to_amount` must be at least \$20. These minimums apply regardless of whether the balance is denominated in fiat currency or a custom pricing unit. When using custom pricing units, the threshold and recharge amounts are evaluated in the custom pricing unit and converted to fiat currency using the conversion rate defined on the customer's rate card. ### Auto recharge with custom pricing units Prepaid balance thresholds support [custom pricing units](/guides/pricing-packaging/make-pricing-changes/use-currency-custompricingunits) in addition to fiat currencies. When a customer's contract uses a custom pricing unit (such as tokens or AI credits), the `threshold_amount` and `recharge_to_amount` are expressed in that custom pricing unit. Metronome converts the recharge amount to fiat currency using the conversion rate defined on the rate card when processing payment. For example, consider an AI platform that prices usage in a custom pricing unit called "AI Tokens," where 1 AI Token = \$0.10 USD: * The customer's contract has a prepaid balance of 500 AI Tokens * You set a `threshold_amount` of 50 AI Tokens and a `recharge_to_amount` of 500 AI Tokens * When the customer's balance drops to 50 AI Tokens, Metronome initiates an auto recharge * Metronome creates a commit for 450 AI Tokens (the difference to reach 500) and charges the customer \$45.00 USD (450 × \$0.10) through the configured payment gateway The conversion rate defined on the rate card determines how the custom pricing unit amount maps to the fiat currency charge. To learn how to set up custom pricing units and configure conversion rates on a rate card, see [Set currencies and custom pricing units](/guides/pricing-packaging/make-pricing-changes/use-currency-custompricingunits). ### Update the contract's prepaid balance threshold Update or add a `prepaid_balance_threshold_configuration` by editing the contract. For example, you can update the `threshold_amount` on a contract. Note that these changes take effect immediately and Metronome forces an evaluation of the customer's current balance on each config change. Edit contracts in the [Metronome app](https://app.metronome.com/) or with the [Metronome API](/api-reference/contracts/edit-a-contract). This API call adds a prepaid balance threshold to a contract: ```json theme={null} { "customer_id": "6352d562-213f-4a6e-819f-58fdabc3f2b9", "contract_id": "e066a32a-3b59-4d07-a91f-a9e084903d45", "update_prepaid_balance_threshold_configuration": { "threshold_amount": 600, "recharge_to_amount": 2700 } } ``` ### Exclude balances from threshold calculations By default, Metronome counts all prepaid commits and credits toward a contract's available balance when evaluating whether a threshold has been reached (with the exception of seat-scoped commits and credits, which are always excluded). Use threshold balance specifiers to further narrow which balances count toward the threshold. This is useful when a contract contains commits or credits that serve different purposes and you don't want all of them factored into recharge decisions. Metronome will only trigger a recharge when the balances matching your specifier drop below the configured threshold\_amount. For example, consider a database company that offers its core product on a prepaid credit model with auto top-up enabled. The company is launching an adjacent AI product and wants to give all customers \$10 in product-specific trial credits for the new product. Without any configuration, Metronome counts all prepaid balances — including the AI trial credits — when evaluating whether a recharge should trigger. This means a customer with a threshold amount of \$15 with \$10 in general credits and \$10 in AI trial credits has a combined balance of \$20, which fails to trigger a top-up even though the customer is running low on their general credits. To ensure top-up fires based on general credit balance only, make a single API call to edit the contract to introduce the new AI trial credit with a custom field (`credit_type: ai_trial`) and exclude that tag from the threshold billing balance calculation. ```json theme={null} { "customer_id": "6352d562-213f-4a6e-819f-58fdabc3f2b9", "contract_id": "e066a32a-3b59-4d07-a91f-a9e084903d45", "update_prepaid_balance_threshold_configuration": { "threshold_balance_specifiers": [{ "exclude": [{ "custom_field_filters": [{ "entity": "ContractCreditOrCommit", "key": "credit_type", "value": "ai_trial" }] }] }] }, "add_credits": [ { "product_id": "ai-trial-product-id", "access_schedule": { "schedule_items": [ { "amount": 1000, "starting_at": "2025-05-01T00:00:00.000Z", "ending_before": "2025-06-01T00:00:00.000Z" } ] }, "custom_fields": { "credit_type": "ai_trial" }, "priority": 1 } ] } ``` When multiple `custom_field_filters` objects are specified within the threshold balance specifier's exclusion condition, Metronome excludes any balance that matches at least one of the filters (OR logic). For example, you may want to run multiple trial credits. The following call to editContract excludes both commits and credits tagged with `credit_type: ai_trial` OR commits and credits tagged with `credit_type: june_product_launch_trial`. ```json theme={null} { "customer_id": "6352d562-213f-4a6e-819f-58fdabc3f2b9", "contract_id": "e066a32a-3b59-4d07-a91f-a9e084903d45", "update_prepaid_balance_threshold_configuration": { "threshold_balance_specifiers": [{ "exclude": [{ "custom_field_filters": [{ "entity": "ContractCreditOrCommit", "key": "credit_type", "value": "ai_trial" }], "custom_field_filters": [{ "entity": "ContractCreditOrCommit", "key": "credit_type", "value": "june_product_launch_trial" }] }] }] } } ``` If multiple custom field key-values are specified within a single `custom_field_filters` array, balances are only excluded when they match all key-value pairs within the filter (AND logic). For example, the following call would exclude only commits and credits that had both the custom fields `credit_type: ai_trial` AND `is_active: true`. Note that you cannot repeat the same custom field key within one custom field filter. ```json theme={null} { "customer_id": "6352d562-213f-4a6e-819f-58fdabc3f2b9", "contract_id": "e066a32a-3b59-4d07-a91f-a9e084903d45", "update_prepaid_balance_threshold_configuration": { "threshold_balance_specifiers": [{ "exclude": [{ "custom_field_filters": [ { "entity": "ContractCreditOrCommit", "key": "credit_type", "value": "ai_trial" }, { "entity": "ContractCreditOrCommit", "key": "is_active", "value": "true" } ] }] }] } } ``` ## Prepaid balance threshold billing lifecycle To best utilize prepaid balance threshold billing, consider its lifecycle: the actions Metronome takes and what actions you may need to take. ### 1. Charge for prepaid balance threshold amount (Metronome) Once configured, Metronome evaluates the remaining balance available to the customer on the contract to determine when the `threshold_amount` has been reached. If the `payment_gate_config` is set to Stripe, Metronome attempts to charge the customer in Stripe. If payment is successful, Metronome creates a commit for the amount that recharges the customer back to the `recharge_to_amount`. ### 2. Manage notifications (you) Metronome fires three types of webhook notifications for prepaid balance threshold billing: * `payment_gate.threshold_reached` when the customer hits their threshold. * `payment_gate.payment_status` after payment has been attempted. The status of that payment, `paid` or `failed`, is denoted in the `payment_status` field. * `payment_gate.payment_pending_action_required` if intervention is required to process payment. Your webhook endpoint must be configured to handle these notifications accordingly. ### 3. Handle failed payments (you) If a payment fails, you receive a `payment_gate.payment_status` with the value of `failed`. Additionally, the contract's `is_enabled` field is set to `false`. You should expect to see a voided invoice in Metronome and Stripe for this transaction. At this point, you should follow up with your customer directly or by creating an automated workflow triggered by this webhook notification. Once you're ready to reattempt payment, set the contract's `is_enabled` field to `true`. This forces the contract to evaluate against the `threshold_amount`, resulting in a new payment attempt. **No Automatic Retries** Metronome does not automatically retry failed payments (as any automatic retries would likely fail, too). ## Use an external payment gate If using the `EXTERNAL` option for `payment_gate_type`, you are responsible for facilitating payment and letting Metronome know the response. Follow this workflow: 1. Set the prepaid balance threshold config with `payment_gate_type` set to `EXTERNAL`. 2. Listen for `payment_gate.external_initiate` that indicates Metronome is ready to receive the outcome of the payment. 3. Save the `workflow_id` - you need this to release the commit. 4. Charge the customer in your payment gateway of choice. 5. Call [commits/threshold-billing/release](/api-reference/credits-and-commits/release-external-payment-gate-threshold-commit/) to either release the commit on successful payment, or cancel the commit in case of failure. # Preview event costs Source: https://docs.metronome.com/guides/customers-billing/optimize-customer-experience/preview-event-cost Preview the cost of customer actions before they’re incurred. Help customers understand the financial impact of their actions before they commit to taking them. The preview events endpoint allows you to simulate how events would affect a customer's invoice without actually processing or billing for them. ## Why preview costs? Cost transparency builds trust and empowers customers to make informed decisions. Common scenarios include: * **Resource-intensive operation cost previews**: Show users how much a compute job or data processing task will cost before confirming execution * **Budget planning**: Help customers forecast costs for planned usage patterns with interactive cost calculators * **What-if analysis**: Let customers explore different usage scenarios to optimize their spending ## How cost preview works The preview events endpoint evaluates events against a customer's actual contract configuration, including all pricing complexity: * **Tiered pricing**: Correctly applies volume discounts and tier transitions * **Commits and credits**: Shows what usage is covered by commit and credit balances and what spills into overage * **Free allotments**: Accounts for included usage in the contract * **Multiple products**: Calculates costs across all products in the contract ## Preview modes There are two different ways you can choose to evaluate preview events: ### Merge mode Combines preview events with the customer's existing usage for the billing period. Use this to show incremental cost impact. **Example**: A customer has used 99 API calls this month (with 100 free). Previewing 5 calls in merge mode shows 1 free and 4 billable. ### Replace mode Evaluates only the preview events, ignoring existing usage. Use this for hypothetical "clean slate" scenarios. **Example**: Show the total monthly cost if a customer only performed the specific actions in the preview. ## Set up a cost preview ### Basic example Preview how 100 compute hours would affect a customer's invoice: ```bash theme={null} curl --request POST \ --url https://api.metronome.com/v1/customers/{customer_id}/previewEvents \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ "events": [ { "event_type": "compute_usage", "timestamp": "2025-11-15T10:00:00Z", "properties": { "compute_hours": "100", "instance_type": "gpu-large" } } ], "mode": "merge" }' ``` ### Response structure The endpoint returns draft invoices showing the calculated costs: ```json theme={null} { "data": [ { "id": "68e0bc1c-a8ec-5765-856b-f896285b4cdb", "issued_at": "2025-12-02T12:00:00+00:00", "start_timestamp": "2025-11-01T00:00:00+00:00", "end_timestamp": "2025-12-01T00:00:00+00:00", "customer_id": "46b2c479-6202-4db6-b392-5a156a9dd5c8", "customer_custom_fields": { "bill_customer_id": "0du01JDIRIUDQKDS6wm2" }, "type": "USAGE", "credit_type": { "id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "name": "USD (cents)" }, "status": "DRAFT", "total": 49000, "external_invoice": null, "contract_id": "688d9619-bd2c-42db-8dcb-288f02f741df", "contract_custom_fields": {}, "line_items": [ { "product_id": "c2ab408b-d212-4dca-a99b-f2b450abad45", "product_type": "UsageProductListItem", "product_custom_fields": { "org_id": "prod_NbZryAoW6ugALt" }, "product_tags": [ "compute" ], "name": "GPU Compute Hours", "type": "usage", "total": 0, "credit_type": { "id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "name": "USD (cents)" }, "starting_at": "2025-11-01T00:00:00+00:00", "ending_before": "2025-12-01T00:00:00+00:00", "netsuite_item_id": "f2b4-50ab-ad45", "unit_price": 4900, "quantity": 10 } ], "custom_fields": {}, "billable_status": "billable" } ] } ``` For customers with multiple active contracts, the endpoint returns separate invoices for each: ```json theme={null} { "data": [ { "contract_id": "contract-1-id", "total": 50000, // ... invoice details for contract 1 }, { "contract_id": "contract-2-id", "total": 25000, // ... invoice details for contract 2 } ] } ``` ### Event deduplication The preview endpoint follows the same deduplication logic as the ingest endpoint: * Events with identical `transaction_id` values passed in the same request payload are deduplicated against each other * Events with identical `transaction_id` values to those passed to `/ingest` in the prior 34 days are deduplicated as well ## Best practices & limitations ### Performance considerations The endpoint has an 8 RPS rate limit per client and is not suitable for real-time validation of every event. Consider these strategies: * **Cache preview results**: When showing repeated calculations for similar usage patterns, cache the results * **Batch multiple events**: Preview multiple events in a single request rather than making separate calls ### Accuracy tips * Include all relevant event properties that affect pricing * Test both `merge` and `replace` modes during development ### Limitations * Customers using SQL-based billable metrics cannot use this endpoint. If SQL BMs are present on the customer invoice being evaluated when passing in events to preview, the endpoint will return a 400 error. # Enforce spend thresholds Source: https://docs.metronome.com/guides/customers-billing/optimize-customer-experience/set-customer-spend-control To reduce fraud in Product-Led Growth (PLG) workflows, Metronome supports *spend threshold billing*. This feature allows you to cap the amount a customer can spend before being charged, thereby limiting your exposure to uncollected revenue. After applying a spend threshold to a contract, watch for webhook notifications to be alerted when payments succeed or fail. ## Create a contract with spend thresholds When you create a contract in Metronome, you can optionally configure a `spend_threshold_configuration`. This config dictates: * The `threshold_amount` for the customer's contract: how much they can spend before a payment attempt is triggered * The `payment_gate_config`: * Configure whether to payment gate the release of the commit and what gateway to use. Select `EXTERNAL` if you are using a gateway Metronome does not currently support. See [Use an external payment gate](/guides/customers-billing/optimize-customer-experience/set-customer-spend-control#using-external-payment-gate) for details. * If using Stripe, configure `PAYMENT_TYPE` to dictate whether payment is sent as an invoice through Stripe Billing or directly as a `paymentIntent` to Stripe's payment gateway. * If using Stripe, select your existing tax provider. * What `product_id` should be used to represent the commit: the `product_id` dictates what the customer sees on their incremental invoice **CONFIGURE BILLING** If using Stripe as your payment gateway, ensure there is a valid Stripe billing configuration set on the contract. Additionally, set `spend_threshold_configuration.is_enabled` to `true` if you want Metronome to immediately evaluate the contract after its creation. Create contracts with spend threshold in the [Metronome app](https://app.metronome.com/) or using the [Metronome API](/api-reference/contracts/edit-a-contract). ```json theme={null} { "customer_id": "8cecbf69-960f-4f66-9575-edebb7d95e88", "rate_card_id": "a7bc3775-b651-46b6-b7e4-d225a7e55c4c", "starting_at": "2025-04-01T00:00:00.000Z", "billing_provider_configuration": { "billing_provider_configuration_id": "211ef270-098f-422c-9ca8-7999bb9156cb" }, ... "spend_threshold_configuration": { "commit": { "product_id": "d6be3bf4-1669-40c9-a8b1-388bb167ab16", "name": "black_mesa_commit", "description": "hello_its_me_im_in_california_dreaming" }, "is_enabled": true, "payment_gate_config": { "payment_gate_type": "NONE" }, "threshold_amount": 200 } } ``` ## Update a contract's spend threshold You can update or add a `spend_threshold_configuration` at any point by editing the user's contract. Add spend threshold limits to existing, non-limited contracts or change existing limits on a contract (for example, after some period of successful payments). Note that these changes take effect immediately. Edit contracts in the [Metronome app](https://app.metronome.com/) or with the [Metronome API](/api-reference/authorization). This API call adds a spend threshold to a contract: ```json theme={null} { "customer_id": "52f5a554-b887-4899-b919-4eb7789c6bf3", "contract_id": "8a5529d3-f353-4231-bedf-7e83f5e9331d", "add_spend_threshold_configuration": { "commit": { "product_id": "d6be3bf4-1669-40c9-a8b1-388bb167ab16", "name": "threshold_charge", "description": "one time for the one time" }, "is_enabled": true, "payment_gate_config": { "payment_gate_type": "STRIPE", "stripe_config": { "payment_type": "INVOICE" } }, "threshold_amount": 100 } } ``` This API call updates an existing spend threshold: ```json theme={null} { "customer_id": "8cecbf69-960f-4f66-9575-edebb7d95e88", "contract_id": "6058587f-763c-400f-a822-3edb3eb2b86b", "update_spend_threshold_configuration": { "is_enabled": true, "threshold_amount": 100, "payment_gate_config": { "payment_gate_type": "STRIPE", "stripe_config": { "payment_type": "INVOICE" } } } } ``` ## Manage notifications and handle failed payments To learn how to manage webhook notifications from Metronome and handle failed customer payments, see [the threshold billing lifecycle](/guides/customers-billing/optimize-customer-experience/prepaid-balance-thresholds#prepaid-balance-threshold-billing-lifecycle). ## Using external payment gate If using the `EXTERNAL` option for `payment_gate_type`, you are responsible for facilitating payment and letting Metronome know the response. Follow this workflow: * Set the spend threshold config with `payment_gate_type` set to `EXTERNAL` * Listen for `payment_gate.external_initiate` that indicates Metronome is ready to receive the outcome of the payment * Save the `workflow_id` - you will need this to release the commit * Charge the customer in your payment gateway of choice * Call [commits/threshold-billing/release](/api-reference/credits-and-commits/release-external-payment-gate-threshold-commit) to either release the commit on successful payment, or cancel the commit in case of failure. # Overview Source: https://docs.metronome.com/guides/customers-billing/overview # Customers & Billing Manage your customer relationships and optimize their billing experience with Metronome's comprehensive customer lifecycle tools. From initial provisioning to ongoing optimization, this section provides everything you need to deliver exceptional customer experiences while scaling your billing effectively with Metronome. ## What you'll cover in **Customers & Billing** This section covers the complete customer journey and billing management, including: * **Customer Management**: Provision customers, manage lifecycles, and control product access * **Customer Experience**: Build dashboards, set spend controls, and provide transparency * **Fraud Protection**: Implement spend thresholds and entitlement controls * **Notifications**: Set up alerts and monitoring for proactive customer management ## Key topics ### Manage customers Handle the complete customer lifecycle from onboarding to renewal: * **Provision Customers**: Create customer objects, configure contracts, and set up ingest aliases * **Customer Lifecycle**: Manage renewals, upsells, downgrades, and contract transitions * **Customer Tiers**: Organize customers by tiers and manage different access levels * **Product Access**: Control which products and features customers can access * **Renewals**: Automate and manage customer contract renewals ### Optimize customer experience Deliver exceptional customer experiences with transparency and control: * **Customer Dashboards**: Build API-powered dashboards showing usage, spend, and commitments * **Spend Controls**: Set customer spending limits and payment gates * **Customer Controls**: Provide customers with self-service billing management * **Balance Tracking**: Show remaining balances and commitment usage * **Reporting**: Deliver comprehensive usage and billing reports ### Manage fraud and entitlements Protect your business while maintaining customer trust: * **Fraud Prevention**: Implement spend thresholds and payment gates * **Entitlement Controls**: Manage product access and feature gating * **Spend Monitoring**: Track unusual usage patterns and spending * **Access Management**: Control customer permissions and product availability ### Set up notifications Stay informed and proactive with comprehensive alerting: * **Create Alerts**: Set up notifications for spend, usage, and commitment thresholds * **Enforce Thresholds**: Automatically trigger actions when limits are reached * **Lifecycle Monitoring**: Track customer contract states and transitions * **Webhook Integration**: Connect alerts to your existing notification systems ## Getting started Ready to optimize your customer billing experience? Start with [provisioning your first customer](/guides/customers-billing/manage-customers/provision-a-customer) or explore [customer dashboard examples](/guides/customers-billing/optimize-customer-experience/customer-dashboards-and-reporting) to see how to provide transparency and control to your customers. # Create alert specifiers Source: https://docs.metronome.com/guides/customers-billing/set-up-notifications/create-alert-specifiers Metronome enables you to configure certain alerts with more granular inclusion and exclusion conditions using alert specifiers. By default, a `low_remaining_contract_credit_and_commit_balance_reached` alert evaluates the **combined** balance of all active commits and credits for a customer. When that total drops below the configured threshold, you receive a single notification. With alert specifiers, you can change what gets evaluated: * **Include** only commits and credits that match a specific set of custom field key values * **Exclude** commits and credits that match certain custom field conditions * **Group** balance evaluations by a custom field key, so you receive a separate notification for each unique value of that key This enables patterns like: * Fire an alert when the balance of product-specific credits (e.g., credits tagged `product_family: abc`) falls below a threshold, independently of your general credit pool * Fire an alert when an individual commit (e.g., commits tagged with `unique_id: commit_xyz`) falls below a threshold * Exclude certain perpetual credits from a general balance alert so it only fires when your standard credits are low ## How alert specifiers work Alert specifiers are defined in the `alert_specifiers` array on a `low_remaining_contract_credit_and_commit_balance_reached` alert. Each specifier contains: * `custom_field_filters`: An array of inclusion conditions that define which commits and credits count toward this alert. If omitted, all commits and credits are included. If a `key` is specified without a `value`, the alert groups evaluations by each unique value of that key. * `exclude`: An array of exclusion conditions. Commits and credits matching any exclusion condition are removed from the evaluation, even if they satisfy the inclusion conditions. Alert specifiers filter on custom fields. You can set custom fields on any commit or credit upon creation. Read more setting and viewing custom fields [here](https://docs.metronome.com/api-reference/custom-fields#custom-fields). Setting or updating a custom field value on a credit or commit will trigger a re-evaluation of any balance alert using `alert_specifiers` applicable to that credit or commit. ### Include specified key-value pairs When you provide `custom_field_filters` with a specific `key` and `value`, only commits and credits matching **all** of those conditions are counted toward the alert threshold. Multiple specifiers in the `alert_specifiers` array are evaluated as **OR** conditions — a commit or credit needs to match only one specifier to be included. Within a single specifier's `custom_field_filters` array, multiple conditions are evaluated as **AND** — a commit or credit must match all listed conditions to be included. **ALERT SPECIFIERS VS. CUSTOM FIELD FILTERS** `alert_specifiers[].custom_field_filter` with a specific `key` and `value` functions identically to the top-level [`custom_field_filter`](https://docs.metronome.com/api-reference/alerts/create-a-threshold-notification#body-custom-field-filters) when creating an alert. Use `alert_specifiers` for greater flexibility. Imagine you are granting a free credit promo on May 4th for a subset of customers and want to know when a customer’s promotional credits reach \$0. Create an alert that fires only when credits tagged `promo_code: may_the_fourth` reach a \$0 threshold. ```json theme={null} POST /v1/alerts/create { "name": "May the Fourth be with you promo alert", "alert_type": "low_remaining_contract_credit_and_commit_balance_reached", "threshold": 0, "alert_specifiers": [ { "custom_field_filters": [ { "entity": "ContractCredit", "key": "promo_code", "value": "may_the_fourth" } ] } ] } ``` ### Include all unique values of a specified key When you provide a `custom_field_filters` entry with a `key` but no `value`, Metronome evaluates the balance **separately for each unique value** of that key. A webhook is sent if the total balance for all balances tagged with the one custom field key-value pair is below the notification threshold, and subsequently when any other groups of balances with the same key but different values meet the threshold. An initial top-level webhook will be sent the first time any key-value pair with the defined key reaches the threshold. **ONE GROUP KEY ONLY** Per-key grouping requires a single specifier with a single `key` and no `value`. You cannot group by more than one key at a time. Imagine your company offers several different promotional credits at a time. Any one customer may have multiple promotions running and wants to be alerted when each individual promotional credit reaches \$0. Instead of creating a dedicated alert to each promotion, create a grouped balance alert for all promotions. ```json theme={null} POST /v1/alerts/create { "name": "Parent promo alert", "alert_type": "low_remaining_contract_credit_and_commit_balance_reached", "threshold": 0, "alert_specifiers": [ { "custom_field_filters": [ { "entity": "ContractCreditorCommit", "key": "promo_code" } ] } ] } ``` For each promotional credit given, create the credit with custom field key `promo_code` and the name of the promotion. The alert will automatically be applied to all customers and all current and future promotions without any code changes needed. When a specific promotional credit on a customer reaches the threshold, you receive a webhook for that specific key-value pair that crossed the threshold. The `alert_specifiers` field in the payload includes the `key` and `value` that triggered the notification. ```json theme={null} { "id": "notif_abc123", "type": "alerts.low_remaining_contract_credit_and_commit_balance_reached", "properties": { "customer_id": "cust_123", "alert_id": "alert_id", "alert_name": "Parent promo alert", "timestamp": "2026-05-07T15:08:44.865Z", "threshold": 0, "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "alert_specifiers": [ { "custom_field_filters": [ { "entity": "ContractCreditOrCommit", "key": "promo_code", "value": "may_7th_promo" } ] } ] } } ``` If this is the first key-value pair to cross the threshold, you will also receive an additional notification for the overall alert. This webhook omits the specific `value` field in `custom_field_filters`, indicating it applies to the alert as a whole. ```json theme={null} { "id": "notif_def456", "type": "alerts.low_remaining_contract_credit_and_commit_balance_reached", "properties": { "customer_id": "cust_123", "alert_id": "alert_id", "alert_name": "Parent promo alert", "timestamp": "2026-05-07T15:08:44.866Z", "threshold": 0, "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "alert_specifiers": [ { "custom_field_filters": [ { "entity": "ContractCreditOrCommit", "key": "promo_code" } ] } ] } } ``` **INFO** You can set up to 3 per-key balance alerts for a single customer with support for up to 1K cardinality (unique key-value pairs) per group key. For keys with more than 1000 values, contact us via the [Metronome support portal](https://support.metronome.com/) to discuss your alert specifier configuration. ### Exclude specified key-value pairs The `exclude` field within a specifier removes specific commits or credits from an otherwise inclusive set. Multiple exclusion entries are evaluated as **OR** conditions — a commit or credit is excluded if it matches any one of them. **EXCLUDED ENTITIES MUST BE INCLUDED IN THE SAME SPECIFIER** Exclusion conditions must target entities that are within the inclusion scope of the same specifier. For example, you cannot create a single alert specifier that includes commits but excludes credits. Create an alert that fires when the general (non-product-specific) credit balance falls below a threshold. Credits tagged `is_product_specific: true` are excluded from this evaluation. ```json theme={null} POST /v1/alerts/create { "customer_id": "cust_abc123", "name": "General credit balance alert", "alert_type": "low_remaining_contract_credit_and_commit_balance_reached", "threshold": 10000, "alert_specifiers": [ { "exclude": [ { "custom_field_filters": [ { "entity": "ContractCreditOrCommit", "key": "is_product_specific", "value": "true" } ] } ] } ] } ``` ## Retrieving alert status You can retrieve the current status of an alert with specifiers using `POST /v1/customer-alerts/get`. To retrieve the status of a specific custom field key-value pair, pass either `custom_field_filters` or `alert_specifiers` in the request body. ```json theme={null} POST /v1/customer-alerts/get { "alert_id": "alert_id", "customer_id": "cust_123", "alert_specifiers": [ { "custom_field_filters": [ { "entity": "ContractCreditOrCommit", "key": "promo_code", "value": "may_7th_promo" } ] } ] } ``` The query will return the status of the specified key-value pair: ```json theme={null} { "data": { "customer_status": "in_alarm", "alert": { "id": "alert_id", "name": "Per-product-family balance alert (excluding data compression)", "alert_type": "low_remaining_contract_credit_and_commit_balance_reached", "status": "active", "threshold": 0, "alert_specifiers": [ { "custom_field_filters": [ { "entity": "ContractCreditOrCommit", "key": "promo_code", "value": "may_7th_promo" } ] } ] } } } ``` ## Resolved webhooks Receive a `low_remaining_contract_credit_and_commit_balance_resolved` webhook when an alert returns to `OK` from `IN_ALARM`. Contact us via the [Metronome support portal](https://support.metronome.com/) if you need this enabled. # Manage your customer lifecycle with Metronome notifications Source: https://docs.metronome.com/guides/customers-billing/set-up-notifications/create-and-manage-notifications Metronome lets you key into real-time customer activity and contract signals with a rich set of notifications that are sent to your configured webhooks. These notifications can help you: * **Deliver timely in-product experiences** like onboarding messages, trial expiration reminders, or managing customer access after usage thresholds are reached * **Power internal workflows** like notifying sales when a contract is expiring or a customer's commit is exhausted, putting them into overages * **Remove customer friction** by notifying customers ahead of key events like a credit expiration or a contract renewal date There are three different types of notifications you can receive from Metronome: * **[Threshold notifications](/guides/customers-billing/set-up-notifications/threshold-notifications)** that fire when specific conditions are met, like spend exceeding a dollar amount or available credit amount dropping below a certain percentage * **[System notifications](/guides/customers-billing/set-up-notifications/system-notifications)** that fire when an object is created or updated or at scheduled points in time, such as when a contract starts or ends * **[Offset notifications](/guides/customers-billing/set-up-notifications/offset-notifications)** that fire at scheduled points in time as defined by a user set policy, such as 7 days before a commit expires or 3 days after a contract starts ## How notifications work Metronome notifications are delivered as JSON formatted [webhook notifications](/guides/platform-configuration/setup-webhooks/) to an endpoint you configure. These notifications are sent asynchronously and are designed to power automated workflows, customer communication, and internal operations. ### Delivery mechanics * **Webhook-based delivery**: All notification types are sent as HTTPS POST requests. * **Standard format**: All payloads follow a consistent JSON schema and include contextual data like `customer_id`, `timestamp`, and relevant object fields. * **Reliable retries**: If the endpoint is unavailable, Metronome will automatically retry delivery using exponential backoff with jitter. Retries continue for up to 48 hours (or until successful). * **At least once delivery**: You may receive duplicate notifications; webhook endpoints should be idempotent. * **Security**: Webhook payloads include a signature header so you can verify the origin ### Evaluation & scheduling | **Notification** | **Timing** | | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | **Threshold** | *Emitted when new usage or data triggers a threshold condition.*
The threshold is evaluated at least once every three minutes. Notifications will fire within 5 minutes of the usage triggering the breach of the threshold being ingested. | | **System** | *Emitted at the point in time the event happens*
Notifications are generated based on the configured timestamp of the object (e.g. contracts start) or action (e.g. contract edited) and are delivered in near real-time. | | **Offset** | *Emitted at the point in time of the defined policy for the event*
Notifications are generated based on the user-defined policy associated with a particular event (e.g. 3 days after commit segment starts or 4 days before contract ends) and are delivered in near real-time | ### Notification states Notification types in Metronome fall into two behavioral models: **stateless** and **stateful**. **System and Offset Notifications** are stateless; they trigger once at a scheduled moment like when a contract ends and they do not track ongoing conditions or transitions. **Threshold Notifications** are stateful; they are continuously evaluated and move between two states: `OK` and `IN_ALARM`. For example, a commit balance notification may enter the `IN_ALARM` state when a customer's remaining balance drops below 10%, and return to `OK` once new prepaid credits are issued. * The threshold notification states are defined as follows: * **EVALUATING:** The threshold has yet to be evaluated, typically due to a customer having just been created * **OK**: The condition has not been met * **IN\_ALARM**: The condition is actively met * When a threshold notification returns to `OK` from `IN_ALARM`, an additional `*_resolved` notification may be sent (if enabled). **DEFAULT STATE FOR THRESHOLD NOTIFICATIONS** The default state for threshold notifications depends on the presence of underlying data. For example, a customer with no active commits would be in an `OK` state for commit balance notifications until a commit is created and consumed. ## Best practices To get the most value from Metronome notifications, we recommend the following: * **Use system notifications for time-based automation.** They offer precise control over the customer lifecycle, notifying you when events like contracts are created or commits have ended. * **Leverage threshold notifications for continuous monitoring.** Set spend, usage, and credit thresholds to warn or remind customers before they reach a limit. Give customers the ability to enable their own notifications (for example, when their balance is low or when spend crosses a certain threshold) for budgeting purposes. * **Use offset notifications for proactive workflows.** For example, fire a `credit.segment.ended` notification 7 days before credits expire to encourage further use. * **Use custom fields to target key customer groups.** Create notifications for just your enterprise customers or those on a specific tier. * **Make endpoints idempotent.** Webhooks are retried if delivery fails, so your systems should safely handle duplicates. * **Log notification deliveries.** Keeping a delivery record helps with auditing and debugging downstream processes. ## Limits Metronome sets different limit restriction behavior for the number of notifications that can be created based on the notification type. ### System and Offset Notifications There are no restrictions on the number of active system and offset notifications that can be created. ### Threshold notifications Threshold notifications do have different limit restrictions depending on if the notification affects a single customer or all active customers: * The number of active threshold configurations that can apply to all customers is 300. * The number of active threshold notifications that can apply to a single customer is 1200. To request higher limits for your Metronome account, please contact us via the [Metronome support portal](https://support.metronome.com/). ## Additional notes * Metronome currently supports webhook delivery only and all notifications are sent to all webhooks you've configured. * We are continuously expanding the types of system notifications and threshold notifications available, so you can cover more billing milestones and build even richer workflows over time. # Offset notifications Source: https://docs.metronome.com/guides/customers-billing/set-up-notifications/offset-notifications Offset notifications allow you to schedule notifications to fire relative to a known date (e.g. a commit's end date or a contract's creation date). They're best for designing proactive, customer-centric experiences. For example, sending a "trial credits expiring soon" email to customers 7 days before their expiration date to encourage further adoption and usage. Offset amounts can be configured in hours, days, weeks, months, and years. ## Offset notification types and payloads **PAYLOAD SCHEMA DIFFERENCES** The payloads schema for offset notifications differ slightly from the payload schema for threshold notifications. Specifically, the payload for offset notifications do not include a `properties` field. Ensure your webhooks are properly configured to handle both notification types. Offset notifications can be configured around any of the system notification types above. A sample payload for offset notifications is below: ```json theme={null} { "id": "c9656215-3e96-59f4-7284-0021bdfd4c9a", "type": "contract.start", "timestamp": "2025-07-02T00:00:00Z", "environment_type": "PRODUCTION", "contract_id": "1bd74703-0854-4730-9549-893585c519e8", "contract_custom_fields": { "ContractType": "PayGo" }, "customer_id": "eadab230-ef95-4c3c-d696-4391c205c982", "customer_custom_fields": { "CustomerType": "Tier2" }, "offset_id": "8ed3d961-7b61-4c0a-8f2b-e546f45c33d6", "offset_duration": "-P3DT12H" } ``` The timestamp included in the offset payload is the time associated with the source event itself, not the offset. For example, for an offset configured to fire 3 days after the contract started, the timestamp will be the contract start time itself, *not* contract start time + 3 days. ## Enabling and managing offset notifications Offset notifications can be enabled and managed through both the UI and the API. Create offset notification interface showing contract end notification configuration **In the UI** 1. Navigate to the **Notifications** tab 2. Click **Create Notification** 3. Choose any of the above system notification types 4. Configure offset details (e.g. 3 days after contract starts, 60 days before commit segment ends) 5. Click **Save** 6. You will begin receiving notifications about this offset event for all customers to all configured webhooks 7. Ensure your webhooks are set up to properly handle the payloads for these notifications. **Via API** 1. Call `POST /v2/notifications/create` 2. Pass in the name of the offset and the offset policy, including type of system event you'd like to create an offset and the associated offset amount in ISO-8601 format 3. A successful response will return details about the created offset including the notification configuration with its unique ID ## Offset behavior by scenario When you enable an offset notification, Metronome starts generating events from that point forward. It does not go back and create events for past data. See the table below for examples of scenarios under which offset notifications will or will not fire. | **Scenario** | **Will the notification fire?** | **Example** | | ---------------------------------------------------------------------------------------- | ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Offset time for an existing entity is already in the past at the time of offset creation | No | A `credit.end - 3d` offset is configured on May 20, but an existing credit ends May 22. The offset fire time (May 19) has already passed, so nothing is sent. | | Entity is created but offset fire time is already in the past | No | A credit is created on May 15 with an end date of May 30. A matching offset (`-30d`) was defined earlier. Since May 1 has already passed, no notification is sent. | | Entity is edited and new offset fire time is in the past | No | A commit originally ended on May 25 with an offset for `-5d` which fired on May 20. On May 22, the end date is edited to May 23. The offset fire time (May 18) has already passed, so nothing is sent. | | Offset is archived before fire time | No | A `contract.end - 1d` offset is scheduled to fire on June 4. The offset config is archived on June 2. The notification does not fire. | | Entity is created after offset config is defined | Yes, if offset fire time is still in the future | A `commit.end - 7d` offset is configured. On May 10, a new commit is created with an end date of May 20. A notification will fire on May 13. | ## Additional caveats There are a few additional caveats for specific offset types: * Offset notifications cannot be configured to fire *before* `.create`, `.edit` and `.archive` events * If you've configured an offset notification to fire before `commit.segment.start`, there is an edge case to be aware of when using this offset type alongside Metronome's recurring commits feature. * For recurring commits, Metronome only generates subsequent child commits at most one future billing period ahead. This means if you have an offset configured to fire before a commit segment starts and that offset duration is *longer than one billing period*, the notification will not fire at its scheduled time. Instead it will fire at the time the next child commit is created. For example, you've set up a monthly recurring commit and configured an offset notification to fire 90 days before a commit segment starts, the offset for that recurring commit will not fire 90 days before the future child commit segment starts because the child commit does not exist yet. Instead, it will fire \~30 days before the future child commit segment starts at the time the next child commit is created as that is when the next billing period becomes available. # System notifications Source: https://docs.metronome.com/guides/customers-billing/set-up-notifications/system-notifications System notifications monitor when events or actions occur based on the configured timestamp of an object (e.g contract start) or the time at which an action occurred (e.g. contract created). They're best for time-based automation workflows around a customer's key lifecycle events. ## System notification types **PAYLOAD SCHEMA DIFFERENCES** The payload schema for system notifications differ slightly from the payload schema for threshold notifications. Specifically, the payload for system notifications do not include a `properties` field. Ensure your webhooks are properly configured to handle both notification types. | **Type** | **Name** | **Details** | | --------------- | ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Contract | `contract.create` | Triggers when a new contract is created | | Contract | `contract.start` | Triggers when a contract is started | | Contract | `contract.edit` | Triggers when a contract is edited | | Contract | `contract.end` | Triggers when a contract ends | | Contract | `contract.archive` | Triggers when a contract is archived | | Commit & Credit | `commit.create` | Triggers when a new commit is created | | Commit & Credit | `commit.edit` | Triggers when a commit is edited | | Commit & Credit | `commit.archive` | Triggers when a commit is archived | | Commit & Credit | `commit.segment.start` | Triggers when a commit segment starts

The segment number that triggered the notification and the total number of commit segments can be found in the payload | | Commit & Credit | `commit.segment.end` | Triggers when a commit segment ends

The segment number that triggered the notification and the total number of commit segments can be found in the payload | | Commit & Credit | `credit.create` | Triggers when a new credit is created | | Commit & Credit | `credit.edit` | Triggers when a credit is edited | | Commit & Credit | `credit.archive` | Triggers when a credit is archived | | Commit & Credit | `credit.segment.start` | Triggers when a credit segment starts

The segment number that triggered the notification and the total number of credit segments can be found in the payload | | Commit & Credit | `credit.segment.end` | Triggers when a credit segment ends

The segment number that triggered the notification and the total number of credit segments can be found in the payload | ## Webhook payload examples ```json contract.create theme={null} { "id": "fca7b4ef-6187-51d5-a9d9-b57f40117728", "type": "contract.create", "timestamp": "2025-09-12T20:20:04Z", "environment_type": "PRODUCTION", "contract_id": "33d206f6-7455-49f6-857d-2172c37db68d", "contract_custom_fields": { "org_key": "g_major" }, "customer_id": "1ed86915-97f1-4d92-8fa6-763c0235093a", "customer_custom_fields": { "bill_customer_id": "0cu21JDIRIUDQKDS6wmx" } } ``` ```json contract.start theme={null} { "id": "4dcef5c4-ed3b-5d0e-baa4-beec74544158", "type": "contract.start", "timestamp": "2025-08-07T00:00:00Z", "environment_type": "PRODUCTION", "contract_id": "33d206f6-7455-49f6-857d-2172c37db68d", "contract_custom_fields": { "org_key": "g_major" }, "customer_id": "1ed86915-97f1-4d92-8fa6-763c0235093a", "customer_custom_fields": { "bill_customer_id": "0cu21JDIRIUDQKDS6wmx" } } ``` ```json contract.edit theme={null} { "id": "ba0d43a2-9426-5219-9191-becdfb43e102", "type": "contract.edit", "timestamp": "2025-09-15T17:27:41Z", "environment_type": "PRODUCTION", "contract_id": "3b1cf6f5-e4ea-449f-acc3-afceffaddea7", "contract_custom_fields": { "org_key": "g_major" }, "customer_id": "541be796-88fa-4081-8f8f-7ac230c43b2c", "customer_custom_fields": { "bill_customer_id": "0cu21JDIRIUDQKDS6wmx" } } ``` ```json contract.end theme={null} { "id": "ba0d43a2-9426-5219-9191-becdfb43e102", "type": "contract.end", "timestamp": "2025-09-15T17:27:41Z", "environment_type": "PRODUCTION", "contract_id": "3b1cf6f5-e4ea-449f-acc3-afceffaddea7", "contract_custom_fields": { "org_key": "g_major" }, "customer_id": "541be796-88fa-4081-8f8f-7ac230c43b2c", "customer_custom_fields": { "bill_customer_id": "0cu21JDIRIUDQKDS6wmx" } } ``` ```json contract.archive theme={null} { "id": "ba0d43a2-9426-5219-9191-becdfb43e102", "type": "contract.archive", "timestamp": "2025-09-15T17:27:41Z", "environment_type": "PRODUCTION", "contract_id": "3b1cf6f5-e4ea-449f-acc3-afceffaddea7", "contract_custom_fields": { "org_key": "g_major" }, "customer_id": "541be796-88fa-4081-8f8f-7ac230c43b2c", "customer_custom_fields": { "bill_customer_id": "0cu21JDIRIUDQKDS6wmx" } } ``` ```json commit.create theme={null} { "id": "23bbd69c-28bb-5f04-b609-ea716b0f00b4", "type": "commit.create", "timestamp": "2025-08-07T00:00:00Z", "environment_type": "PRODUCTION", "commit_id": "529a023b-3d3c-52b1-b6d5-4d3dd06c6cb0", "commit_custom_fields": { "tier_key": "f_minor" }, "contract_id": "33d206f6-7455-49f6-857d-2172c37db68d", "contract_custom_fields": { "org_key": "g_major" }, "parent_recurring_commit_id": "0719c77c-e3e1-4d1d-bb59-6cee63773f24", "customer_id": "1dd86915-97f1-4d92-8fa6-763c0235093a", "customer_custom_fields": { "bill_customer_id": "0cu21JDIRIUDQKDS6wmx" } } ``` ```json commit.edit theme={null} { "id": "33bbd69c-28bb-5f04-b609-ea716b0f00b4", "type": "commit.edit", "timestamp": "2025-08-07T00:00:00Z", "environment_type": "PRODUCTION", "commit_id": "529a023b-3d3c-52b1-b6d5-4d3dd06c6cb0", "commit_custom_fields": { "tier_key": "f_minor" }, "contract_id": "33d206f6-7455-49f6-857d-2172c37db68d", "contract_custom_fields": { "org_key": "g_major" }, "parent_recurring_commit_id": "0719c77c-e3e1-4d1d-bb59-6cee63773f24", "customer_id": "1dd86915-97f1-4d92-8fa6-763c0235093a", "customer_custom_fields": { "bill_customer_id": "0cu21JDIRIUDQKDS6wmx" } } ``` ```json commit.archive theme={null} { "id": "43bbd69c-28bb-5f04-b609-ea716b0f00b4", "type": "commit.archive", "timestamp": "2025-08-07T00:00:00Z", "environment_type": "PRODUCTION", "commit_id": "529a023b-3d3c-52b1-b6d5-4d3dd06c6cb0", "commit_custom_fields": { "tier_key": "f_minor" }, "contract_id": "33d206f6-7455-49f6-857d-2172c37db68d", "contract_custom_fields": { "org_key": "g_major" }, "parent_recurring_commit_id": "0719c77c-e3e1-4d1d-bb59-6cee63773f24", "customer_id": "1dd86915-97f1-4d92-8fa6-763c0235093a", "customer_custom_fields": { "bill_customer_id": "0cu21JDIRIUDQKDS6wmx" } } ``` ```json commit.segment.start theme={null} { "id": "92adc38c-671c-59dd-8f2e-39fc7482a4df", "type": "commit.segment.start", "timestamp": "2025-08-07T00:00:00Z", "environment_type": "PRODUCTION", "commit_id": "529a023b-3d3c-52b1-b6d5-4d3dd06c6cb0", "commit_custom_fields": { "tier_key": "f_minor" }, "contract_id": "33d206f6-7455-49f6-857d-2172c37db68d", "contract_custom_fields": { "org_key": "g_major" }, "parent_recurring_commit_id": "0718c77c-e3e1-4d1d-bb59-6cee63773f24", "segment_index": 0, "segment_count": 1, "segment_id": "dea59112-dadb-52c4-8789-304e2cddff92", "customer_id": "1ed86915-97f1-4d92-8fa6-763c0235093a", "customer_custom_fields": { "bill_customer_id": "0cu21JDIRIUDQKDS6wmx" } } ``` ```json commit.segment.end theme={null} { "id": "a2adc38c-671c-59dd-8f2e-39fc7482a4df", "type": "commit.segment.end", "timestamp": "2025-08-07T00:00:00Z", "environment_type": "PRODUCTION", "commit_id": "529a023b-3d3c-52b1-b6d5-4d3dd06c6cb0", "commit_custom_fields": { "tier_key": "f_minor" }, "contract_id": "33d206f6-7455-49f6-857d-2172c37db68d", "contract_custom_fields": { "org_key": "g_major" }, "parent_recurring_commit_id": "0718c77c-e3e1-4d1d-bb59-6cee63773f24", "segment_index": 0, "segment_count": 1, "segment_id": "dea59112-dadb-52c4-8789-304e2cddff92", "customer_id": "1ed86915-97f1-4d92-8fa6-763c0235093a", "customer_custom_fields": { "bill_customer_id": "0cu21JDIRIUDQKDS6wmx" } } ``` ```json credit.create theme={null} { "id": "23bbd69c-28bb-5f04-b609-ea716b0f00b4", "type": "credit.create", "timestamp": "2025-08-07T00:00:00Z", "environment_type": "PRODUCTION", "credit_id": "529a023b-3d3c-52b1-b6d5-4d3dd06c6cb0", "credit_custom_fields": { "tier_key": "f_minor" }, "contract_id": "33d206f6-7455-49f6-857d-2172c37db68d", "contract_custom_fields": { "org_key": "g_major" }, "parent_recurring_credit_id": "0719c77c-e3e1-4d1d-bb59-6cee63773f24", "customer_id": "1dd86915-97f1-4d92-8fa6-763c0235093a", "customer_custom_fields": { "bill_customer_id": "0cu21JDIRIUDQKDS6wmx" } } ``` ```json credit.edit theme={null} { "id": "33bbd69c-28bb-5f04-b609-ea716b0f00b4", "type": "credit.edit", "timestamp": "2025-08-07T00:00:00Z", "environment_type": "PRODUCTION", "credit_id": "529a023b-3d3c-52b1-b6d5-4d3dd06c6cb0", "credit_custom_fields": { "tier_key": "f_minor" }, "contract_id": "33d206f6-7455-49f6-857d-2172c37db68d", "contract_custom_fields": { "org_key": "g_major" }, "parent_recurring_credit_id": "0719c77c-e3e1-4d1d-bb59-6cee63773f24", "customer_id": "1dd86915-97f1-4d92-8fa6-763c0235093a", "customer_custom_fields": { "bill_customer_id": "0cu21JDIRIUDQKDS6wmx" } } ``` ```json credit.archive theme={null} { "id": "43bbd69c-28bb-5f04-b609-ea716b0f00b4", "type": "credit.archive", "timestamp": "2025-08-07T00:00:00Z", "environment_type": "PRODUCTION", "credit_id": "529a023b-3d3c-52b1-b6d5-4d3dd06c6cb0", "credit_custom_fields": { "tier_key": "f_minor" }, "contract_id": "33d206f6-7455-49f6-857d-2172c37db68d", "contract_custom_fields": { "org_key": "g_major" }, "parent_recurring_credit_id": "0719c77c-e3e1-4d1d-bb59-6cee63773f24", "customer_id": "1dd86915-97f1-4d92-8fa6-763c0235093a", "customer_custom_fields": { "bill_customer_id": "0cu21JDIRIUDQKDS6wmx" } } ``` ```json credit.segment.start theme={null} { "id": "92adc38c-671c-59dd-8f2e-39fc7482a4df", "type": "credit.segment.start", "timestamp": "2025-08-07T00:00:00Z", "environment_type": "PRODUCTION", "credit_id": "529a023b-3d3c-52b1-b6d5-4d3dd06c6cb0", "credit_custom_fields": { "tier_key": "f_minor" }, "contract_id": "33d206f6-7455-49f6-857d-2172c37db68d", "contract_custom_fields": { "org_key": "g_major" }, "parent_recurring_credit_id": "0718c77c-e3e1-4d1d-bb59-6cee63773f24", "segment_index": 0, "segment_count": 1, "segment_id": "dea59112-dadb-52c4-8789-304e2cddff92", "customer_id": "1ed86915-97f1-4d92-8fa6-763c0235093a", "customer_custom_fields": { "bill_customer_id": "0cu21JDIRIUDQKDS6wmx" } } ``` ```json credit.segment.end theme={null} { "id": "a2adc38c-671c-59dd-8f2e-39fc7482a4df", "type": "credit.segment.end", "timestamp": "2025-08-07T00:00:00Z", "environment_type": "PRODUCTION", "credit_id": "529a023b-3d3c-52b1-b6d5-4d3dd06c6cb0", "credit_custom_fields": { "tier_key": "f_minor" }, "contract_id": "33d206f6-7455-49f6-857d-2172c37db68d", "contract_custom_fields": { "org_key": "g_major" }, "parent_recurring_credit_id": "0718c77c-e3e1-4d1d-bb59-6cee63773f24", "segment_index": 0, "segment_count": 1, "segment_id": "dea59112-dadb-52c4-8789-304e2cddff92", "customer_id": "1ed86915-97f1-4d92-8fa6-763c0235093a", "customer_custom_fields": { "bill_customer_id": "0cu21JDIRIUDQKDS6wmx" } } ``` ## Enabling and managing system notifications System notifications can be enabled and managed through both the UI and the API. Notifications list interface showing various notification types and their status **In the UI** 1. Navigate to the **Notifications** tab 2. Find the system notification that you'd like to enable. All available system notifications will appear in the notifications list view and be disabled by default for any account 3. Click on the notification 4. Click the toggle next to **Status** to enable 5. Confirm action to enable 6. You will begin receiving notifications about this system event for all customers to all configured webhooks 7. Ensure your webhooks are set up to properly handle the payloads for these notifications **Via API** 1. Call `POST /v2/notifications/edit` 2. Pass in the policy of the system notification you'd like to enable (e.g. `contract.create`) and `is_enabled` set to true 3. A successful response will return a 200 response code **HISTORICAL DATA LIMITATION** When you enable a system notification, Metronome starts generating events from that point forward. It does not go back and create events for past data. Additionally, the policy for system notifications cannot be edited. # Threshold notifications Source: https://docs.metronome.com/guides/customers-billing/set-up-notifications/threshold-notifications Threshold notifications monitor real-time metrics and trigger when defined thresholds are crossed. They're best for proactive monitoring and usage-driven workflows. Threshold notifications fall into three main categories: * **Commit and Credit threshold notifications** monitor remaining balances of commits or credits. They can be used to notify a customer when they've used 90% of their commit, or to flag accounts that are close to running out of prepaid credits. **INFO** Commit and credit threshold notifications alert on the balance of both customer and contract level commits and credits. [Individual seat-scoped credits](https://docs.metronome.com/guides/pricing-packaging/subscription/provision-your-customer#individual-seat-credit) are not included in the threshold calculation for these notifications. * **Spend and Usage threshold notifications** track how much a customer has spent or used over a given billing cycle. They can be used to trigger a message when a customer crosses a spend threshold, such as \$5,000, or to power logic for offering upgrades once a customer approaches a certain usage cap. * **Invoice threshold notifications** monitor invoice totals after commits and credits have been applied to customer spend. They can be used to proactively notify customers when spend surpasses pre-configured budgets. ## Threshold notification types #### Contract credit balance **Alert Type:** `alerts.low_remaining_contract_credit_balance_reached` Triggers when a customer's credit balance reaches or drops below a set amount. If multiple credits exist for a customer, Metronome sums up the remaining balances across all credits to compare against the threshold. To notify on a specific credit, set a custom field on the credit in Metronome and use advanced filters to evaluate only credits with that specific custom field value. #### Contract credit percentage **Alert Type:** `alerts.low_remaining_contract_credit_percentage_reached` Triggers if the customer's percentage of available credits on all active credits of that credit type (currency or pricing unit) reaches or goes below a set threshold. To notify on a specific credit, set a custom field on the credit in Metronome and use advanced filters to evaluate only credits with that specific custom field value. #### Commitment balance **Alert Type:** `alerts.low_remaining_commit_balance_reached` Triggers when a customer's commit balance reaches or drops below a set amount. If multiple commits exist for a customer, Metronome sums up the remaining balances across all commits to compare against the threshold. To notify on a specific commit, set a custom field on the commit in Metronome and use advanced filters to evaluate only commits with that specific custom field value. #### Commitment percentage **Alert Type:** `alerts.low_remaining_commit_percentage_reached` Triggers if the customer's percentage of available commits on all active commits of that credit type (currency or pricing unit) reaches or goes below a set threshold. To notify on a specific commit, set a custom field on the commit in Metronome and use advanced filters to evaluate only commits with that specific custom field value. #### Contract credit and commit balance **Alert Type:** `alerts.low_remaining_contract_credit_and_commit_balance_reached` Triggers when a customer's combined commit and credit balance reaches or drops below a set amount. If multiple commits and credits exist for a customer, Metronome sums up the remaining balances across all commits and credits to compare against the threshold. #### Seat balance **Alert Type:** `alerts.low_remaining_seat_balance_reached` Triggers when a customer's seat balance reaches or drops below a set amount. Metronome sums up the remaining balances for the specific seat across all commits and credits to compare against the threshold. Use the required `seat_filter` parameter to scope the notification to seat balances associated with seat-based subscriptions with a specific `seat_group_key`. Metronome will sum up the remaining balances for each seat across all commits and credits to compare against the threshold. Optionally, use the `seat_filter.seat_group_value` parameter to scope the notification to a specific seat. #### Spend threshold **Alert Type:** `alerts.spend_threshold_reached` Triggers if the customer's usage-based spend prior to commit and credit drawdown for their current billing period reaches or goes beyond the set threshold. This notification evaluates against the sum of all usage-based charges for a particular customer, including usage drawdowns on credits and commits. Commit purchases are not factored into a customer's spend threshold notification. For example, if the threshold is set at \$10,000, \$7,000 in usage charges plus a \$3,000 commit purchase will not trigger the notification. Additionally, spend notifications are evaluated *only* against direct spend in a specific credit type. A spend notification threshold configured for a currency always evaluates to `ok` if you are using a custom pricing unit for a customer's line items. To avoid this, configure spend notification thresholds to use the same pricing unit as the line items on a customer's invoice. To notify on a specific contract type, set a custom field on the contract in Metronome and use advanced filters to evaluate only contracts with that specific custom field value. Optionally, use the `group_values` advanced filter parameter with this notification type to evaluate only usage associated with a specific group key:group value pair. You can also filter on `group_key` to evaluate usage across all group values for that key. #### Billable metric usage **Alert Type:** `alerts.usage_threshold_reached` Triggers if the customer's usage of a particular billable metric in their current billing period reaches or goes beyond your set threshold. The current billing period for a customer is calculated by taking the earliest start date and the latest end date across all active invoices. #### Invoice total **Alert Type:** `alerts.invoice_total_reached` Triggers if any of the customer's active invoices reaches or exceeds the configured threshold. This notification evaluates against the net invoice total after any credits, commits, or other adjustments have been applied. Each active invoice for the customer is evaluated separately. Additionally, only invoices in the specified currency are evaluated. To notify on a specific invoice type, use advanced filters to target the particular invoice type. ## Webhook payload examples ```json low_remaining_credit_balance_reached theme={null} { "id": "445b849e-1366-4580-a6cc-f488e27c059f", "properties": { "customer_id": "ac39ecc3-87ee-4d58-8ec0-24041464dddd", "alert_id": "445b849e-1366-4580-a6cc-f488e27c059f", "timestamp": "2024-10-07T15:08:44.865Z", "threshold": 20000, "alert_name": "Credit balance low", "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "remaining_balance": 5000, "triggered_by": "usage" }, "type": "alerts.low_remaining_credit_balance_reached" } ``` ```json spend_threshold_reached theme={null} { "id": "7f8a9b2c-3d4e-5f6g-7h8i-9j0k1l2m3n4o", "properties": { "customer_id": "b2c3d4e5-f6g7-h8i9-j0k1-l2m3n4o5p6q7", "alert_id": "7f8a9b2c-3d4e-5f6g-7h8i-9j0k1l2m3n4o", "timestamp": "2024-10-07T16:30:15.123Z", "threshold": 10000, "alert_name": "Spend threshold exceeded", "current_spend": 12500, "triggered_by": "usage" }, "type": "alerts.spend_threshold_reached" } ``` ```json low_remaining_commit_balance_reached theme={null} { "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "properties": { "customer_id": "c3d4e5f6-g7h8-i9j0-k1l2-m3n4o5p6q7r8", "alert_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "timestamp": "2024-10-07T14:45:30.456Z", "threshold": 5000, "alert_name": "Commit balance low", "commit_id": "d4e5f6g7-h8i9-j0k1-l2m3-n4o5p6q7r8s9", "remaining_balance": 1200, "triggered_by": "usage" }, "type": "alerts.low_remaining_commit_balance_reached" } ``` ```json usage_threshold_reached theme={null} { "id": "e5f6g7h8-i9j0-k1l2-m3n4-o5p6q7r8s9t0", "properties": { "customer_id": "f6g7h8i9-j0k1-l2m3-n4o5-p6q7r8s9t0u1", "alert_id": "e5f6g7h8-i9j0-k1l2-m3n4-o5p6q7r8s9t0", "timestamp": "2024-10-07T17:15:45.789Z", "threshold": 1000000, "alert_name": "API calls threshold exceeded", "billable_metric_id": "g7h8i9j0-k1l2-m3n4-o5p6-q7r8s9t0u1v2", "current_usage": 1250000, "triggered_by": "usage" }, "type": "alerts.usage_threshold_reached" } ``` ```json invoice_total_reached theme={null} { "id": "h8i9j0k1-l2m3-n4o5-p6q7-r8s9t0u1v2w3", "properties": { "customer_id": "i9j0k1l2-m3n4-o5p6-q7r8-s9t0u1v2w3x4", "alert_id": "h8i9j0k1-l2m3-n4o5-p6q7-r8s9t0u1v2w3", "timestamp": "2024-10-07T18:00:00.000Z", "threshold": 50000, "alert_name": "Invoice total exceeded", "invoice_id": "j0k1l2m3-n4o5-p6q7-r8s9-t0u1v2w3x4y5", "invoice_total": 55000, "triggered_by": "invoice_generation" }, "type": "alerts.invoice_total_reached" } ``` ## Creating and managing threshold notifications Threshold notifications can be created and managed through both the UI and the API. You can define what thresholds you care about and which customers to target. Create threshold notification interface showing spend threshold configuration **In the UI** 1. Navigate to the **Notifications** tab 2. Click **Create Notification** 3. Choose any of the above threshold notification types 4. Configure threshold details and custom field level targeting where applicable 5. Determine whether you'd like the notification to evaluate customers that already meet the threshold or only trigger on customers that cross the threshold in the future 6. Select customers that notification should be applied to 7. Click **Save** 8. Metronome will begin evaluating the selected customers against the defined threshold and will trigger a notification to your configured webhooks when the customer crosses the threshold 9. Ensure your webhooks are set up to properly handle the payloads for these notifications **Via API** 1. Call `POST /v1/alerts/create` 2. Pass in the alert type, name and threshold in the request body 3. Optionally pass in additional filters relevant to the alert type 4. A successful response will return a CustomerAlert object containing the notification configuration with its unique ID and current status To get the real-time evaluation status for a specific threshold notification-customer pair, you can call the `POST /v1/customer-alerts/get` endpoint. This endpoint provides instant visibility into whether a customer has triggered a threshold condition, enabling you to monitor account health and take proactive action based on current state. This endpoint is useful for periodic checking of a customer's threshold notification status, but shouldn't be scraped. You should instead rely on the webhook notification to understand when customers are moved to `IN_ALARM`. Threshold notifications can be archived in the UI or via API, removing them from active monitoring. ## Threshold notification evaluation triggers To assess whether or not a threshold notification should be sent, Metronome routinely evaluates customers with associated notifications in real time as usage is sent to Metronome. If a customer's watched value—credit balance, spend, and so on—hits the threshold, a threshold notification is sent. There are two possible triggers for an evaluation: * Usage events are ingested * Customer metadata changes (for example, a contract is assigned or a new ingest alias is assigned) Specifically, any CRUD (create, retrieve, update, and delete) action impacting notifications, customers, customer ingest aliases, contract, commitments, and credits are considered metadata changes and trigger a notification evaluation. Threshold alerts have notifications sent within minutes of that condition being met. # Design usage events Source: https://docs.metronome.com/guides/events/design-usage-events Success with Metronome depends on the data you provide, so it's important to properly design your usage events. Follow these three principles: * Work backward from what you *need* * Work forward from what you *have* * Maximize your flexibility This guide uses a hypothetical scenario where you're a developer at a Content Delivery Network (CDN) and you've been tasked with integrating your system into Metronome to support usage-based billing. ### Work backward from what you need​ Start with your existing requirements or an ideal invoice and work backward from there. In the case of a CDN, your company charges customers based on their monthly data usage. However, the exact pricing details are unknown. This is fine as pricing can be applied and adjusted later as long as the required metrics are in place. An additional consideration is that your customer support team wants to take advantage of Metronome as a real-time data platform to notify customers when there's an unusual spike in traffic for their sites. For both invoicing and notifications, you need to measure data transfer, so the bare minimum usage event looks like: ```json theme={null} { "event_type": "transfer", "properties": { "bytes": "1234", }, "transaction_id": "...", "customer_id": "...", "timestamp": "..." } ``` This supports a billable metric like "sum of `bytes` for all events of type `transfer` (for a given customer, for a given billing period)." ### Work forward from what you have​ Next, consider what data you have available and how that data might help in the future. * **When to send events** Your system could track total data transfer internally and send an incremental per-customer summary to Metronome. Or you could send Metronome an event every time a web page is served. Both options provide the same invoicing ability at the end of each month, which route you choose depends upon your needs. * **What data to include** There's a lot more information to potentially include in usage events. For example, you could include which data center served the page, what domain was hosted, the type of file, or even what URL was accessed. None of this is immediately necessary for invoicing, but it could be useful for your own records. The timing and content of usage events are often heavily influenced by what is available in your existing system. At your hypothetical CDN company, imagine that you perform global log aggregation with Apache Flume. In this case, there's a central data store with detailed access logs available, making it easy to send those log messages to Metronome in the form of individual usage events as they arrive. Now imagine that you don't have such global aggregation. Instead, each data center keeps its own independent log and sends hourly summaries back to the central data store, broken down by domain. Each data center must send usage events directly to Metronome, but unfortunately the code there doesn't have access to the customer database, so the data center can't determine what `customer_id` to fill in for each event. In this case, the hourly summaries are probably the best option. From the central location, it's easy to look up the owner of each domain and provide the appropriate `customer_id`. Before deciding to send the hourly summaries, you check back with the customer support team about those traffic spike notifications they wanted. They assure you that the hourly cadence is fast enough for the notifications they want to send. ### Maximize your flexibility​ Business needs evolve over time. Rather than attempting to anticipate all future requirements, focus on creating a flexible system that can easily adapt to changes. In Metronome, flexibility is maximized when you **send as much data as possible**. Metronome's stream pipeline can handle high event throughput, and irrelevant data is discarded during processing. This means there's no downside to sending information that isn't going to be used right away. There is, however, a big upside to sending extra information. Suppose that your hypothetical CDN company starts getting feedback from customers that they don't understand their bills. Many customers are responsible for more than one domain and would like to be able to see how much each domain is contributing to their total usage. As the assigned developer, your executives ask you to fix this. If your usage event didn't include the domain, you'd need to go back to your code and add it. But you chose to send as much data as possible, so it's already there: ```json theme={null} { "event_type": "transfer", "properties": { "domain": "www.example.com", "data_center": "US-WEST-3", "bytes": "12345789", }, "transaction_id": "...", "customer_id": "...", "timestamp": "..." } ``` All you need to do is query the Metronome API for usage data grouped by `domain`. And your customers are happy with the new breakdown on their invoices. As time passes and your customer base grows, the finance team discovers a worrisome problem. Your company has been billing customers based on their total data transfer, but your bandwidth costs are different in different parts of the world. In some cases, you're actually losing money by undercharging for data transfer in certain regions. As before, if your usage events didn't include information about where the data transfer occurred, you'd have to go back into your code and add it. But because you already decided to send as much data as possible, there's a `data_center` field that will work. Billable metrics in Metronome can filter usage events in a variety of ways, so you are able to use a mapping of data center names to regions to define a new billable metric for each region. Going forward, you can bill based on those new metrics, where you can set individual prices for each region. **BILLABLE METRICS ARE NOT RETROACTIVE** Metronome operates on streams; changes you make only affect future data collection and aggregation. New billable metrics cannot be applied to historical data. # Usage events at scale Source: https://docs.metronome.com/guides/events/high-volume-ingestion As your business grows, your event volume will grow with it. Your billing architecture needs to support everything from initial product launches to sudden spikes in adoption, without introducing delays or hitting unexpected processing limits. Metronome’s infrastructure is designed to provide this reliability at scale. We support companies who send billions of events per day and rely on Metronome to accurately calculate their millions of end-customer’s billing in real-time. This guide outlines how Metronome's architecture is built for scale and how you can leverage its capabilities to ensure data integrity as you grow. ## High throughput event ingest Metronome's infrastructure supports up to 110,000 events per second (6.6 million events per minute) without requiring pre-aggregation or rollups. Default ingest rate limit starts at 5,000 events per second. If you need higher throughput, contact us via the [Metronome support portal](https://support.metronome.com/) to increase it. When scaling to send high event volumes, batching your events helps you take full advantage of this capacity. You can batch 100 events per request sent to Metronome’s ingest endpoint. To do so, submit an array of usage event objects using a POST request and sending events whose schema matches the structure outlined. Learn more about sending usage to Metronome [here](/guides/events/send-usage-events). ```bash theme={null} curl https://api.metronome.com/v1/ingest \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '[ { "transaction_id": "event-20250910-001", "customer_id": "customer_123", "timestamp": "2025-09-10T12:00:00Z", "event_type": "ai-run", "properties": { "model_name": "gpt-5", "input_tokens": "10000", "output_tokens": "1000", "type": "input" } }, { "transaction_id": "event-20250910-002", "customer_id": "customer_456", "timestamp": "2025-09-10T12:05:00Z", "event_type": "ai-run", "properties": { "model_name": "gpt-4o", "input_tokens": "8000", "output_tokens": "900", "type": "output" } } // additional 98 events objects ]' ``` ## Monitor event data in the UI The Metronome UI offers direct access to inspect your event pipeline through our dedicated event explorer. This feature is useful to validate that Metronome has successfully ingested events, that they've been successfully matched to Metronome objects like [Billable Metrics](/guides/get-started/core-concepts/create-billable-metrics), and to identify duplicate events. With the events UI, you can: * See summary-level time-based entire event stream or isolated duplicate event graphs * Includes custom time-frame viewing options * Search by customer, duplicates, billable metrics, and transaction IDs * View complete usage event payloads from individual events * View usage event attribution to matched customer and [billable metrics](/guides/get-started/core-concepts/create-billable-metrics) * Export a CSV event log Event stream in Metronome UI Event summary in Metronome UI ## Maintaining data integrity at scale The Metronome UI is great for spot-checking and quick validation. For sustained reliability at high volumes, you’ll want automated, programmatic checks that run continuously and alert you before issues affect customers or revenue. Use the guidance below to build a more scalable event posture. High-volume event ingestion requires effective monitoring and maintenance of your event pipeline. Metronome provides end-to-end visibility and self-serve tooling to help you resolve issues before they impact your business. * **Queue and Retry:** You should follow industry-standard best practices around queueing, retries, message queue logging, alerting, and use of dead-letter queues. Please see [here](send-usage-events#queue-and-retry) for Metronome’s recommendations. * **Usage Pipeline Observability:** Metronome's [**Event Search API**](/api-reference/usage/search-events) allows you to sample raw events and validate that they are matching active billable metrics. This is a critical control for preventing silent revenue loss if an upstream system changes an event schema. * **Seamless Backfills and Recovery:** If an incident occurs, you need to be able to recover data quickly. Metronome offers a 34-day historical ingest and deduplication window processed through the same [ingest endpoint](/api-reference/usage/ingest-events). This extended window ensures you can replay more than 24 hours of traffic and re-rate draft invoices and credit ledgers in real time. Corrections beyond 34 days is handled by our operations team and is usually completed promptly. # Send usage events Source: https://docs.metronome.com/guides/events/send-usage-events After [designing your usage events](/guides/events/design-usage-events), send them to Metronome. This guide describes what data to send and best practices to ensure event accuracy. Send usage events to Metronome through the [/ingest](/api/#operation/ingest-v1) endpoint or by [connecting Metronome to Segment](/integrations/platform-integrations/segment). ## Usage event structure A usage event is a JSON object with the following fields: ```jsx theme={null} { "transaction_id": string, // (required) unique identifier for this event "customer_id": string, // (required) which customer the event applies to "timestamp": string, // (required) when the event happened "event_type": string, // (required) the kind of event, such as page_view or sent_email "properties": object, // (optional) key/value pairs with event details } ``` ### `transaction_id` Metronome uses the `transaction_id` to ignore duplicate events. Once a usage event is accepted with a given transaction ID, subsequent events within the next 34 days with the same ID are treated as duplicates and ignored. ### `customer_id` The `customer_id` specifies which of your customers is responsible for any billing associated with the event. There are two ways to identify a Metronome customer in usage events: a customer ID or an *ingest alias*. Ingest aliases are useful when sending events using an identifier from your system, such as an email address or account number. Each customer in Metronome may have multiple ingest aliases, and usage events with a `customer_id` matching any of those aliases can be attributed towards that customer's usage. ### `timestamp` The `timestamp` must be an [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) string with a 4-digit year, such as `2025-01-23T01:23:45Z`. When querying usage data or producing an invoice, this field is used to select only events that happened in a certain time range. Timestamps more than 24 hours in the future are rejected by the API. ### `event_type` The `event_type` works along with the `properties` map to describe the details of the event. For example, a content delivery network (CDN) might generate events of the type `http_request` with properties like `domain` and `bytes_sent` to support billing based on data transfer. They might also generate a different type of event, `cache_invalidation`, with a property `number_of_files`. You can name title the `event_type` as needed, but for more insights check out how to [design billable metrics](/guides/get-started/core-concepts/create-billable-metrics). ### `properties` All keys and values in the `properties` map should be represented as strings, even though the values are often numeric. This prevents the loss of precision that often occurs in systems that use floating point numbers. Internally, Metronome uses arbitrary precision decimals to provide exact results of computation. Again, we advise sharing more data here than you might need initially so you can flexibly utilize this later on if need be. ## Queue and retry If usage events are lost on their way to Metronome, you’ll lose revenue. If you're sending events through the API, you need to be resilient to failures such as network issues or process crashes. A good way to gain this resilience is to put your usage events on a reliable queue such as [Amazon SQS](https://aws.amazon.com/sqs/) or [RabbitMQ](https://www.rabbitmq.com/), and have a process pull from that queue and push events to Metronome. If your call to the Metronome `/ingest` endpoint fails with a network error or a `5xx` HTTP status code, some of your events may have been ingested, but others may not. Always retry a failed call to `/ingest` until you receive a `200` status code. The unique `transaction_id` in each event prevents duplicate processing, so retries are always safe. If your call to the Metronome `/ingest` endpoint fails with a `429` HTTP status code, you have exceeded one of our rate limits. In this case, you should back off and retry the call after a delay. If the request continues to be rate-limited, wait for an exponentially increasing amount of time between retries. Avoid auto-retries on 4xx If a call to `/ingest` fails with a `4xx` HTTP status code (besides `429`), this indicates an issue with the payload. **Do not** automatically retry such a call. Instead, put the event aside in a [dead letter queue](https://en.wikipedia.org/wiki/Dead_letter_queue) and trigger an alarm so you can investigate the failure and resolve the issue. ## Message queue logging When first integrating with Metronome, it's helpful to enable logging in your message queue. This lets you audit exactly what usage events are being sent to Metronome. Also enabling logging any time you make a change to your usage events. ## Trial ingestion resilience To test your system’s response to elevated error rates from Metronome’s API, Metronome can set up an automatic failure rate of your choice (we recommend 20%). Contact us via the [Metronome support portal](https://support.metronome.com/) to specify the % failure rate, when to enable and disable the test, and if you'd like to apply it to your sandbox or production instance. ### Aggregation A billable metric aggregates over a single property by default. For example, if you're an email sending service, you might have a usage event that looks like: ```json theme={null} { "event_type": "email_sent", "properties": { "num_recipients": "8", "size": "1000" } // ... } ``` Already, this event supports charging customers based on how many emails they sent or the maximum size of an email. For further aggregation, like total data sent (`num_recipients` \* `size`), use [SQL-based billable metrics](/guides/get-started/core-concepts/billable-metrics-sql-editor). ## Heartbeat event idempotence Usage events typically fall into one of two categories: an event that occurs when a user takes some action, or a periodic "heartbeat" that measures the current state—a common approach in infrastructure services. For example, a service selling computation might send a per-node heartbeat to Metronome each minute describing the CPU and disk utilization on that node. These events could be aggregated into the metrics "CPU minutes" and "gigabyte minutes." It's important for heartbeat events to ensure that usage is only counted once. This is accomplished by choosing a deterministic `transaction_id` for duplicate events to have the same ID. Metronome guarantees that only one event with a given `transaction_id` is processed. In the example of a per-node per-minute heartbeat, you might structure a transaction ID as follows: ``` _ ``` where `unix_now()` is a function that returns the number of seconds since the [Unix epoch](https://en.wikipedia.org/wiki/Unix_time). By including both the node ID and a minute-granularity timestamp in the transaction ID, it's guaranteed that duplicate events from the same node in the same minute is ignored. Using this type of `transaction_id` means you also don't have to worry about sending events too often. We recommend sending *two or more heartbeats* per measurement period. Duplicates are safely ignored, and by using this approach, you decrease the risk of missing a measurement period due to timer imprecision or a temporary delay. Changes to usage events may cause breakages Usage events are designed to target very specific billable metrics, so if the data structure changes, it could prevent downstream metrics from being properly recorded. It's best to contact us via the [Metronome support portal](https://support.metronome.com/) any time you are adjusting the structure of your usage events. We can help validate and test the change with you to avoid any disruption. ## Ensure Metronome does not block critical paths Metronome has been expressly designed to use safely in the most critical parts of your application. In accordance with availability best practices, we suggest verifying that Metronome is not a blocker in your customer creation path. Since Metronome can match events sent at any time before or after customer creation using ingest aliases, we recommend creating the customer in your system first—then creating the matching customer record in Metronome asynchronously. # API quickstart Source: https://docs.metronome.com/guides/get-started/api-quickstart Get to your first invoice with the Metronome API This guide walks you through Metronome's API to set up billing programmatically — from creating your first billable metric to seeing a working invoice. **Looking for the UI guide?** If you prefer configuring billing through the Metronome dashboard, see the [UI Quickstart](/guides/get-started/metronome-dashboard-quickstart). ## Prerequisites * A Metronome sandbox account ([sign up here](https://signup.metronome.com/)) * Your Metronome sandbox API token (**Developer → API tokens** in the dashboard) ### Environments & authentication The environment is determined entirely by your API token. A sandbox token only works with sandbox data; a production token only works with production data. All requests require a Bearer token. ## Step 1: Understand how the pieces fit together Before building anything, here's how Metronome's core objects connect: Metronome core objects Metronome separates *metering* (what you measure) from *rating* (what you charge). You can change pricing without changing your event instrumentation, and vice versa. Here's what each object does: * **Usage Events** — Raw records of customer activity sent to Metronome (e.g., "customer X used 1,500 input tokens on model gpt-5 at timestamp Z") * **Billable Metrics** — Rules that aggregate your events into billable quantities (e.g., "sum the `input_tokens` property for events of type `llm_request`"). This is also where you define **group keys** — the properties you'll use to price by or display on invoices. * **Products** — Named line items on an invoice. * **Rate Cards** — A centralized price book assigning a price to each product. A single rate card can be shared across many customers, making pricing updates easy to roll out. * **Contracts** — Customer-specific agreements referencing a rate card, defining the billing period, and optionally including credits, commits, or overrides. * **Packages** — Encodes your rate card and contract details in a single package to be applied across new customers. * **Invoices** — Automatically generated each billing period based on a customer’s recurring charges and usage, rated against the contract. **What you need to create (in this order):** 1. A billable metric 2. A product 3. A rate card with rates for each product 4. A customer 5. A contract linking the customer to the rate card Then you send events and Metronome handles the rest. ## Step 2: Design your event schema Before creating anything, decide what your usage events look like. Every event sent to Metronome has this structure: ```json theme={null} { "transaction_id": "2026-03-09T14:30:00Z_req_abc123", "customer_id": "your-customer-uuid-in-metronome", "event_type": "llm_request", "timestamp": "2026-03-09T14:30:00Z", "properties": { "model": "gpt-5", "input_tokens": "1500", "output_tokens": "350", "provider": "openai", "region": "us-east-1", "user_id": "user_8f3a", "cost": "0.0042" } } ``` ### Required fields * **`transaction_id`** — Unique per event for idempotency. If the same `transaction_id` is sent twice, Metronome deduplicates. Tip: combine timestamp + request ID. * **`customer_id`** — Metronome customer UUID, or an `ingest_alias` configured on the customer (so you can use your own internal ID). * **`event_type`** — String connecting this event to a billable metric. Must exactly match the billable metric's `event_type_filter` `in_values`. * **`timestamp`** — ISO 8601 format. Must be within the last **34 days** (Metronome's backdating window). Future-dated events are rejected. ### Properties (metric-dependent) * **`properties`** — Key-value pairs. **All values should be strings** (even numbers) — Metronome uses arbitrary-precision decimals internally to avoid floating point issues. Metronome also supports up to **2,000 properties** per event. Properties serve three purposes: 1. **Aggregation** — The value you sum, count, or max (e.g., `input_tokens`, `duration_seconds`) 2. **Group keys** — Dimensions for pricing (e.g., `model`, `region`) or invoice display (e.g., `user_id`, `project_id`). **Must be defined on the billable metric first.** 3. **Metadata** — Context for customers, COGS analysis, or future-proofing (e.g., `provider`, `cost`, `endpoint`) **Send more properties than you think you need.** You can always ignore unused properties, but you cannot retroactively add group keys to a billable metric. ### Common event patterns | Use Case | `event_type` | Key Properties | | -------------- | ------------------ | ----------------------------------------------------------------------- | | AI/LLM API | `llm_request` | `model`, `input_tokens`, `output_tokens`, `provider`, `user_id`, `cost` | | Generic API | `api_call` | `endpoint`, `method`, `response_code`, `user_id` | | Compute | `compute_usage` | `instance_type`, `duration_seconds`, `region`, `user_id` | | Storage | `storage_snapshot` | `storage_gb`, `tier`, `user_id` | | Seats/Licenses | `active_seat` | `user_id`, `role`, `plan` | For more patterns, see [Event Design Patterns](/guides/events/design-usage-events). ## Step 3: Create a billable metric API Reference: [Create a Billable Metric](/api-reference/billable-metrics/create-a-billable-metric) ### Example — Count API calls (simple): ```bash theme={null} curl -X POST https://api.metronome.com/v1/billable-metrics/create \ -H "Authorization: Bearer $METRONOME_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "API Calls", "aggregation_type": "count", "event_type_filter": { "in_values": ["api_call"] } }' ``` ### Example — Sum tokens with group keys: ```bash theme={null} curl -X POST https://api.metronome.com/v1/billable-metrics/create \ -H "Authorization: Bearer $METRONOME_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "Input Tokens", "aggregation_type": "sum", "aggregation_key": "input_tokens", "event_type_filter": { "in_values": ["llm_request"] }, "property_filters": [ { "name": "model", "exists": true }, { "name": "input_tokens", "exists": true }, { "name": "user_id", "exists": true } ], "group_keys": [["model"], ["user_id"]] }' ``` ### Aggregation types `count` | `sum` | `unique` | `max` | `latest` * **`count`** — Number of matching events (API calls, requests) * **`sum`** — Sum of a numeric property (tokens, bytes, seconds) * **`max`** — Maximum value in a window (peak storage, concurrent connections) ### Group keys Group keys determine what you price by and display on invoices. They work like `GROUP BY` in SQL. **Define them here — they can't be added later.** For streaming BMs, properties used as group keys must appear in `property_filters` with `"exists": true`. | Group key | Downstream use | Example | | --------------- | ---------------------- | ------------------------------ | | `model` | Pricing group key | Different price per AI model | | `region` | Pricing group key | Different price per region | | `instance_type` | Pricing group key | Different price per GPU | | `user_id` | Presentation group key | Per-user invoice breakdowns | | `project_id` | Presentation group key | Per-project invoice breakdowns | ### SQL billable metrics For complex calculations (daily averages, percentile-based billing, weighted formulas), use SQL billable metrics. Any column returned by your SQL query besides `value` can be used as a group key. [Learn more →](/guides/get-started/core-concepts/billable-metrics-sql-editor) **Billable metrics are immutable after creation** You cannot add or change group keys, property filters, or aggregation settings. Include group keys for any dimension you might price by or display in the future. Example — unique users per region: ```sql theme={null} SELECT count(DISTINCT properties.user_id) as value, properties.region FROM events WHERE event_type = 'api_request' GROUP BY properties.region ``` Here, `region` is returned as a column and can be used as a pricing group key on the product. ## Step 4: Create a product API Reference: [Create a Product](/api-reference/products/create-a-product) ### Example — Usage product with group keys: ```bash theme={null} curl -X POST https://api.metronome.com/v1/contract-pricing/products/create \ -H "Authorization: Bearer $METRONOME_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "Input Tokens", "type": "usage", "billable_metric_id": "", "pricing_group_key": ["model"], "presentation_group_key": ["user_id"] }' ``` ### Product types * **`usage`** — Variably priced based on customer usage (requires a billable metric) * **`subscription`** — Recurring fee on a schedule (platform fees, seat licenses) * **`composite`** — Percentage charge on a usage product * **`fixed`** — One-time or scheduled charges (commits, credits, one-time fees) ### Group key assignment | I want to... | Field | Notes | | ---------------------------------------- | ------------------------ | --------------------------------------------------- | | Different prices per dimension value | `pricing_group_key` | Each value gets its own rate entry on the rate card | | Invoice line-item breakdowns (same rate) | `presentation_group_key` | Groups line items by this dimension | | One flat price | Don't set either | Simple billing | Group keys on the product must be a subset of group keys on the underlying billable metric. *(Optional Conversions)* Add a **quantity conversion** — e.g., send individual tokens but display and price per million tokens on the invoice. Add a **rounding conversion** — e.g., send seconds but round and display to the nearest minute on the invoice. ## Step 5: Create a rate card API Reference: [Create a Rate Card](/api-reference/rate-cards/create-a-rate-card) **Best practice:** Use a centralized rate card shared across customers. Rate updates propagate to all referencing contracts. ### Create the rate card: ```bash theme={null} curl -X POST https://api.metronome.com/v1/contract-pricing/rate-cards/create \ -H "Authorization: Bearer $METRONOME_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{"name": "Standard Pricing"}' ``` ### Add Rates: ```bash theme={null} curl --request POST \ --url https://api.metronome.com/v1/contract-pricing/rate-cards/addRates \ --header 'Authorization: Bearer $METRONOME_API_TOKEN' \ --header 'Content-Type: application/json' \ --data ' { "rate_card_id": "d7abd0cd-4ae9-4db7-8676-e986a4ebd8dc", "rates": [ { "product_id": "13117714-3f05-48e5-a6e9-a66093f13b4d", "starting_at": "2020-01-01T00:00:00.000Z", "entitled": true, "rate_type": "FLAT", "price": 100, "pricing_group_values": { "region": "us-west-2", "cloud": "aws" } }, { "product_id": "13117714-3f05-48e5-a6e9-a66093f13b4d", "starting_at": "2020-01-01T00:00:00.000Z", "entitled": true, "rate_type": "FLAT", "price": 120, "pricing_group_values": { "region": "us-east-2", "cloud": "aws" } } ] } ' ``` ### Add dimensional pricing (one entry per value): ```bash theme={null} curl -X POST https://api.metronome.com/v1/contract-pricing/rate-cards/rates/add \ -H "Authorization: Bearer $METRONOME_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "rate_card_id": "", "product_id": "", "starting_at": "2026-03-01T00:00:00Z", "rate_type": "flat", "price": 1.50, "entitled": true, "pricing_group_values": { "model": "gpt-5" } }' ``` Repeat with different `pricing_group_values` for each dimension value (e.g., `gpt-5-mini` at \$0.30). ### Additional capabilities * **Tiered pricing** — Volume-based tiers via the `tiers` field on a rate entry * **Custom Pricing Units** — Create under **Offering → Pricing Units** in the UI, then reference the `credit_type_id` on the rate card for credit-based billing. [Learn more →](/guides/pricing-packaging/make-pricing-changes/use-currency-custompricingunits) * **Commit rates** — Rates that apply specifically to prepaid commit drawdown ## Step 6: Create a customer and contract ### Create a customer: API Reference: [Create a Customer](/api-reference/customers/create-a-customer) ```bash theme={null} curl -X POST https://api.metronome.com/v1/customers/create \ -H "Authorization: Bearer $METRONOME_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "Test Customer", "ingest_aliases": ["my-internal-customer-id"] }' ``` The `ingest_aliases` field lets you send events keyed on your own internal customer identifier instead of Metronome's UUID. You can map sub-organizations to a single customer using multiple aliases. ### Create a contract: API Reference: [Create a Contract](/api-reference/contracts/create-a-contract) ```bash theme={null} curl -X POST https://api.metronome.com/v1/contracts/create \ -H "Authorization: Bearer $METRONOME_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "customer_id": "", "rate_card_id": "", "starting_at": "2026-03-01T00:00:00Z", "usage_statement_schedule": { "frequency": "MONTHLY" } }' ``` This creates a contract **without a billing provider** — invoices will be generated in Metronome and viewable in the dashboard. To have invoices automatically sent to Stripe, add `billing_provider_configuration`: ```json theme={null} "billing_provider_configuration": { "billing_provider": "stripe", "delivery_method": "direct_to_billing_provider" } ``` For full Stripe setup (account-level connection, customer billing config, etc.), see the [Stripe Integration Guide](/integrations/invoice-integrations/stripe). ## Step 7: Send your first events API Reference: [Ingest Events](/api-reference/usage/ingest-events) Batch up to **100 events** per request. Metronome supports approximately **6.6 million events per minute** with batching. ```bash theme={null} curl -X POST https://api.metronome.com/v1/ingest \ -H "Authorization: Bearer $METRONOME_API_TOKEN" \ -H "Content-Type: application/json" \ -d '[{ "transaction_id": "test-001", "customer_id": "", "event_type": "llm_request", "timestamp": "2026-03-09T12:00:00Z", "properties": { "model": "gpt-5", "input_tokens": "1500", "user_id": "user_1" } }, { "transaction_id": "test-002", "customer_id": "", "event_type": "llm_request", "timestamp": "2026-03-09T12:01:00Z", "properties": { "model": "gpt-5-mini", "input_tokens": "800", "user_id": "user_2" } }]' ``` ### Important behaviors * A **`200` response** means events were accepted for ingestion. Check the response body for per-event errors. * Note that if there's no matching BM for the `event_type` or required properties are not included, events are stored but may not appear in usage calculations. Be sure to create billable metrics before sending events if they are needed for rating. * Events can be **backdated up to 34 days**. Events with future timestamps are rejected. * **`transaction_id`** is used for deduplication. Sending the same ID twice won't double-bill. * **Only ingest endpoint events are metered.** API calls for managing customers, contracts, etc. are not billable. ### Verify your events Navigate to **Events** in the dashboard. Search by `transaction_id`. Click into an individual event to see if it matched a billable metric and customer — this is the fastest diagnostic. Refresh the page if events don't appear immediately. The aggregate "Total event count" may lag. ### Troubleshooting 1. **Click into the event** on the Events page — verify it matched a BM and customer. 2. **Check the API response** from your ingest call for per-event errors. 3. If events match a BM + customer **but don't appear on the invoice:** The pricing group key values in the event likely don't match any rate on the rate card. For example, `"model": "gpt-5"` vs `"model": "gpt5"` (missing hyphen) will silently fail to rate. 4. **Verify your API token** is for sandbox (not production, or vice versa). ## Step 8: Verify your invoice Navigate to **Customers → \[Your Customer] → Invoices** in the dashboard. The draft invoice should show your usage and charges. **Invoice lifecycle:** 1. **Draft** — Accumulates usage throughout the billing period (viewable in Metronome) 2. **Finalized** — Locked at end of billing period. There is a **24 hour grace period** at the end of the billing period before invoices are finalized to make any necessary changes to an invoice. 3. **Sent to billing provider** — If Stripe is connected, pushed within \~1 hour of finalization. Payment status managed in Stripe's dashboard. 4. **Paid / Failed** — Collection handled by your billing provider Verify the draft invoice shows correct usage quantities and charges based on your event ingestion and rate card pricing. If you see usage (under Events) but no charges on the invoice, check that your events are matching the pricing group key values on your rate card. ## Ready for more? * [**Embeddable Customer Dashboards**](/guides/customers-billing/optimize-customer-experience/customer-dashboards-and-reporting) — Self-serve usage visibility for your customers * [**Webhooks**](/guides/platform-configuration/setup-webhooks) — Invoice lifecycle, balance alerts, payment events * [**Alerts & Notifications**](/guides/customers-billing/set-up-notifications/create-and-manage-notifications) — Spend thresholds, balance notifications * [**Credits & Commits**](/guides/pricing-packaging/apply-credits-and-commits) — Prepaid balances, enterprise commitments * [**Stripe Integration**](/integrations/invoice-integrations/stripe) — Automated payment collection * [**Revenue Recognition**](/guides/reporting-insights/financial-reporting/revenue-recognition) — ASC 606 / IFRS 15 * [**Production Checklist**](/guides/implement-metronome/production-checklist) — When you're ready to go live (new API token, same base URL, live Stripe keys) # Build with the Metronome SDKs Source: https://docs.metronome.com/guides/get-started/developer-sdks Metronome provides powerful software development kits (SDKs) designed to seamlessly integrate Metronome billing APIs into your applications. The SDKs for Python, Go, Ruby, Node.js, and Java offer developers flexible options for implementing Metronome's capabilities across platforms and environments. This page walks through a basic but powerful usage-based billing system in Python, Node, Ruby, or Golang: 1. Install and configure the Metronome SDK. 2. Send usage events to Metronome, laying the foundation for consumption-based billing. 3. Create a billable metric to define how Metronome should aggregate and measure usage. 4. Create a customer in the system and associate them with usage events. 5. Set up pricing and packing for your product. 6. Create a contract for the customer, enabling automatic invoice generation based on their usage. ## SDK features​ Each SDK GitHub repository contains detailed documentation, examples, and resources to help you make the most of Metronome in your applications: * [Python SDK](https://github.com/Metronome-Industries/metronome-python/blob/main/README.md) * [Go SDK](https://github.com/Metronome-Industries/metronome-go/blob/main/README.md) * [Ruby SDK](https://github.com/Metronome-Industries/metronome-ruby/blob/main/README.md) * [Node.js SDK](https://github.com/Metronome-Industries/metronome-node/blob/main/README.md) * [Java SDK](https://github.com/Metronome-Industries/metronome-java/blob/main/README.md) Core SDK features include: * **Strong typing of Metronome endpoints and objects** enhance developer productivity with better autocomplete and IDE support for Metronome objects. * **Pagination support** simplifies the process of retrieving and managing paginated data from Metronome services. * **Automatic retry support** by default retries each request upon failure up to three times. You can configure it to any number of retries. Use this to automatically handle transient errors and network issues without needing to implement retry logic. While this guide covered the fundamentals, Metronome offers much more functionality to model different business models. Check out the SDK repo to see what’s possible. ## 1. Install and configure the SDK​ First install and configure the SDK in your environment: ```bash Python theme={null} pip install --pre metronome-sdk ``` ```bash Node theme={null} npm install @metronome/sdk ``` ```bash Ruby theme={null} gem install metronome-sdk ``` ```bash Go theme={null} go get -u 'github.com/Metronome-Industries/metronome-go' ``` Next, configure the SDK by passing a valid [API key](/api-reference/authorization) as the authorization bearer token. By default, the SDK looks for the API key under the environment variable `METRONOME_BEARER_TOKEN`. In this example, it'll be passed as an argument to the constructor instead. ```python Python theme={null} from metronome import Metronome client = Metronome( # Defaults to os.environ.get("METRONOME_BEARER_TOKEN") if omitted bearer_token="My bearer token", ) ``` ```javascript Node theme={null} import Metronome from '@metronome/sdk' const client = new Metronome({ // Defaults to os.environ.get("METRONOME_BEARER_TOKEN") if omitted bearerToken: "My bearer token", }); ``` ```ruby Ruby theme={null} require "bundler/setup" require "metronome_sdk" metronome = MetronomeSDK::Client.new( bearer_token: "My Bearer Token" # defaults to ENV["METRONOME_BEARER_TOKEN"] ) ``` ```go Go theme={null} package main import ( "context" "github.com/Metronome-Industries/metronome-go" "github.com/Metronome-Industries/metronome-go/option" ) func main() { client := metronome.NewClient( option.WithBearerToken("My bearer token"), // defaults to os.LookupEnv("METRONOME_BEARER_TOKEN") if omitted ) } ``` ## 2. Send usage events​ The usage-based billing model builds upon captured usage data from users on your platform. Metronome accepts usage payloads of all formats through the [/ingest](/api-reference/usage/ingest-events) endpoint. Use the SDK to send data to Metronome: ```python Python theme={null} response = client.v1.usage.ingest( usage=[ { "transaction_id": "9995a70e-a2c5-4904-b96d-70de446f420e", "timestamp": "2024-08-01T00:00:00Z", "customer_id": "team@example.com", "event_type": "language_model", "properties": { "model": "langModel4", "user_id": "johndoe", "tokens": 1000000 } } ] ) ``` ```javascript Node theme={null} async function main() { await client.V1.usage.ingest([ { transaction_id: '9995a70e-a2c5-4904-b96d-70de446f420e', timestamp: "2024-08-01T00:00:00.000Z", customer_id: 'team@example.com', event_type: 'language_model', properties: { model: "langModel4", user_id: "johndoe", tokens: 1000000 } }, ]); } main(); ``` ```ruby Ruby theme={null} result = metronome.v1.usage.ingest( usage: [ { transaction_id: '9995a70e-a2c5-4904-b96d-70de446f420e', timestamp: "2024-08-01T00:00:00.000Z", customer_id: 'team@example.com', event_type: 'language_model', properties: { model: "langModel4", user_id: "johndoe", tokens: 1000000 } } ] ) puts(result) ``` ```go Go theme={null} err := client.V1.Usage.Ingest(context.TODO(), metronome.UsageIngestParams{ Usage: []metronome.UsageIngestParamsUsage{{ TransactionID: metronome.F("9995a70e-a2c5-4904-b96d-70de446f420e"), Timestamp: metronome.F("2024-08-01T00:00:00Z"), CustomerID: metronome.F("team@example.com"), EventType: metronome.F("language_model"), Properties: metronome.F(map[string]interface{}{ "model": "langModel4", "user_id": "johndoe", "tokens": 1000000, }), }}, }) if err != nil { panic(err.Error()) } ``` The properties used in this example include: * `usage`, allows you to pass in multiple event payloads in a request. Metronome supports passing up to 100 events within a single request. * `transaction_id`, provides Metronome with the unique idempotency key for the event. Metronome deduplicates based on this ID, allowing you to send events potentially many times without worrying about double-charging your customers. * `timestamp`, the time when the event occurred. Send in events with any timestamp up to 34 days in the past. * `customer_id`, the customer ID in Metronome or any other customer identifier you want to define. For example, customer email or internal customer ID within your platform. Later steps show how to define these custom identifiers for your customers in Metronome. * `event_type`, an arbitrary string that you can define within the request. * `properties`, an arbitrary set of data to include within the payload for metering and grouping within Metronome. Success with Metronome depends on the data you provide, so it's important to design [usage events](/guides/events/design-usage-events) well. To view all events sent to Metronome, go to the **Events tab** in the [Metronome app](https://app.metronome.com/). For the event sent in the example, it successfully made it into the Metronome system. But, it hasn’t been matched yet with a metric to start metering or a customer in the system. View an event ## 3. Create a billable metric​ A billable metric describes a per-customer aggregation over a subset of usage events. By configuring a billable metric, you instruct Metronome how to match usage events to products you charge for. Here’s an example billable metric configuration that matches against the usage event sent in the previous example: ```python Python theme={null} response = client.v1.billable_metrics.create( name="langModel4", event_type_filter={ "in_values": [ "language_model" ] }, property_filters=[ { "name": "model", "exists": True, "in_values": [ "langModel4" ] }, { "name": "user_id", "exists": True }, { "name": "tokens", "exists": True } ], aggregation_key="tokens", aggregation_type="SUM", group_keys=[ ["user_id"] ] ) billable_metric_id = response.data.id ``` ```javascript Node theme={null} const billableMetricsResponse = await client.V1.billableMetrics.create({ name: "langModel4", event_type_filter: { in_values: [ "language_model" ] }, property_filters: [ { name: "model", exists: true, in_values: [ "langModel4" ] }, { name: "user_id", exists: true }, { name: "tokens", exists: true, } ], aggregation_key: "tokens", aggregation_type: "SUM", group_keys: [ ["user_id"] ] }); const billableMetricId = billableMetricsResponse.data.id; ``` ```ruby Ruby theme={null} response = client.v1.billable_metrics.create( name: "langModel4", event_type_filter: { in_values: [ "language_model" ] }, property_filters: [ { name: "model", exists: true, in_values: [ "langModel4" ] }, { name: "user_id", exists: true }, { name: "tokens", exists: true } ], aggregation_key: "tokens", aggregation_type: "SUM", group_keys: [ ["user_id"] ] ) billable_metric_id = response.data.id ``` ```go Go theme={null} billableMetricResponse, err := client.V1.BillableMetrics.New(context.TODO(), metronome.BillableMetricNewParams{ Name: metronome.F("langModel4"), EventTypeFilter: metronome.F(metronome.EventTypeFilterParam{ InValues: metronome.F([]string{"language_model"}), }), PropertyFilters: metronome.F([]metronome.PropertyFilterParam{ { Name: metronome.F("model"), Exists: metronome.F(true), InValues: metronome.F([]string{ "langModel4", }), }, { Name: metronome.F("user_id"), Exists: metronome.F(true), }, { Name: metronome.F("tokens"), Exists: metronome.F(true), }, }), AggregationKey: metronome.F("tokens"), AggregationType: metronome.F(metronome.BillableMetricNewParamsAggregationTypeSum), }) if err != nil { panic(err.Error()) } billableMetricID := billableMetricResponse.Data.ID ``` The properties used in the code include: * `name`, the name to give your billable metric. * `event_type_filter`, the set of values that matched against the `event_type` field in the usage events. Omit this if you want to match against all event types. * `property_filters`, the set of properties you expect to find on the usage payload. If you mark a property as `exists=True` in the billable metric definition and the property not found on the payload, the billable metric won’t match to the event. * `aggregation_key`, used to define the property with the relevant value to aggregate on. * `aggregation_type`, used to tell Metronome how to aggregate the values specified by the `aggregation_key` as they come into the system. Supported operations are `SUM`, `COUNT`, and `MAX`. * `group_keys`, used to define properties to separate the usage data into different buckets, similar to a `group by` clause in SQL. The example above set `user_id` as a group key, so you can display the invoice separated by the amount of tokens that each user consumed. Billable metric Note that billable metrics only match usage events sent after the billable metric is created. Now that you created the metric, send in another usage event to ensure that it matches as expected: ```python Python theme={null} response = client.v1.usage.ingest( usage=[ { "transaction_id": "7e28f511-d66c-4517-91ef-a92c108e56de", "timestamp": "2024-08-01T00:00:00Z", "customer_id": "team@example.com", "event_type": "language_model", "properties": { "model": "langModel4", "user_id": "johndoe", "tokens": 1000000 } } ] ) ``` ```javascript Node theme={null} await client.V1.usage.ingest([ { transaction_id: '7e28f511-d66c-4517-91ef-a92c108e56de', timestamp: "2024-08-01T00:00:00.000Z", customer_id: 'team@example.com', event_type: 'language_model', properties: { model: "langModel4", user_id: "johndoe", tokens: 1000000 } }, ]); ``` ```ruby Ruby theme={null} response = client.v1.usage.ingest( usage: [ { transaction_id: "7e28f511-d66c-4517-91ef-a92c108e56de", timestamp: "2024-08-01T00:00:00Z", customer_id: "team@example.com", event_type: "language_model", properties: { model: "langModel4", user_id: "johndoe", tokens: 1000000 } } ] ) ``` ```go Go theme={null} err := client.V1.Usage.Ingest(context.TODO(), metronome.UsageIngestParams{ Usage: []metronome.UsageIngestParamsUsage{{ TransactionID: metronome.F("7e28f511-d66c-4517-91ef-a92c108e56de"), Timestamp: metronome.F("2024-08-01T00:00:00Z"), CustomerID: metronome.F("team@example.com"), EventType: metronome.F("language_model"), Properties: metronome.F(map[string]interface{}{ "model": "langModel4", "user_id": "johndoe", "tokens": 1000000, }), }}, }) if err != nil { panic(err.Error()) } ``` The new usage event matches the defined billable metric. Billable metric with a usage event ## 4. Create a customer​ Usage events impact billing for customers, so the next step is to create a customer in Metronome. Use the SDK to create a customer, similar to this example: ```python Python theme={null} response = client.v1.customers.create( name="Example Customer", ingest_aliases=[ "team@example.com" ] ) metronome_customer_id = response.data.id ``` ```javascript Node theme={null} const customerResponse = await client.V1.customers.create({ name: "Example Customer", ingest_aliases: [ "team@example.com" ] }); const customerId = customerResponse.data.id; ``` ```ruby Ruby theme={null} response = client.v1.customers.create( name: "Example Customer", ingest_aliases: [ "team@example.com" ] ) metronome_customer_id = response.data.id ``` ```go Go theme={null} customerResponse, err := client.V1.Customers.New(context.TODO(), metronome.CustomerNewParams{ Name: metronome.F("Example Customer"), IngestAliases: metronome.F([]string{ "team@example.com", }), }) if err != nil { panic(err.Error()) } customerID := customerResponse.Data.ID ``` The properties used in this example include: * `name`, the display name for the customer in Metronome. * `ingest_aliases`, a list of identifiers used to match a Metronome customer against a usage event. Ingest aliases are useful if you want to start flowing in usage for customers before they’re created in Metronome. To do this, use the ID from your application’s customer table. New customer In the example, you associated the newly created customer with the ingest alias `team@example.com`, so the previous event gets matched correctly. After you set the customer up for invoicing in the next section, this event contributes to their current invoice. Billable metric for the customer ## 5. Set up pricing and packaging​ Next, set up prices and packaging, defined using products and rate cards. In the example, you want to charge your customer based on their usage of `langModel4` at a rate of \$0.50 per 1 million tokens. The first step is to create a `product` for your billable metric. A product is where you configure the billable metric for presentation on the eventual invoice. It’s also where you can associate the metric with items in external systems, like the Stripe customer ID. Learn about the configuration options for products in the API docs for the [create product](/api-reference/products/create-a-product) endpoint. Create a product associated to the billable metric, similar to this example: ```python Python theme={null} response = client.v1.contracts.products.create( name="Language Model 4 Tokens (millions)", type="USAGE", billable_metric_id=billable_metric_id, # ID from create billable metric response presentation_group_key=["user_id"], quantity_conversion={ "conversion_factor": 1000000, "operation": "divide" } ) product_id = response.data.id ``` ```javascript Node theme={null} const productResponse = await client.V1.contracts.products.create({ name: "Language Model 4 Tokens (millions)", type: "USAGE", billable_metric_id: billableMetricId, // ID from create billable metric response presentation_group_key: ["user_id"], quantity_conversion: { conversion_factor: 1000000, operation: "divide" } }); const productId = productResponse.data.id; ``` ```ruby Ruby theme={null} response = client.v1.contracts.products.create( name: "Language Model 4 Tokens (millions)", type: "USAGE", billable_metric_id: billable_metric_id, # ID from create billable metric response presentation_group_key: ["user_id"], quantity_conversion: { conversion_factor: 1000000, operation: "divide" } ) product_id = response.data.id ``` ```go Go theme={null} productResponse, err := client.V1.Contracts.Products.New(context.TODO(), metronome.ProductNewParams{ Name: metronome.F("Language Model 4 Tokens (millions)"), Type: metronome.F(metronome.ProductNewParamsTypeUsage), BillableMetricID: metronome.F(billableMetricID), // ID from create billable metric response PresentationGroupKey: metronome.F([]string{ "user_id", }), QuantityConversion: metronome.F(metronome.QuantityConversionParam{ ConversionFactor: metronome.F(1000000.0), Operation: metronome.F(metronome.QuantityConversionParamOperationDivide), }), }) if err != nil { panic(err.Error()) } productID := productResponse.Data.ID ``` The properties used in this example include: * `name`, the name of the product that appears on the invoice. Often a cleaned presentation of the billable metric name (`Language Model 4 Tokens (millions)` versus `langModel4`). * `type`, determines how a product gets charged. Supported types include `usage`, `fixed`, `composite` (for percentages of other usage products), and `subscription`. * `billable_metric_id`, associates the product presentation with an existing billable metric. * `presentation_group_key`, used to group line items on your invoice by a given property value. * `quantity_conversion`, used to multiply or divide quantities displayed on the final invoice. For example, charge by million tokens (mTok) while sending in usage at the individual token level. Converted billable metric Next, attach a price for the product by adding rates to a rate card. Build a rate card for your new product, similar to this example: ```python Python theme={null} response = client.v1.contracts.rate_cards.create( name="Language Model List Pricing", description="Prices for all language models.", ) rate_card_id = response.data.id response = client.v1.contracts.rate_cards.rates.add( rate_card_id=rate_card_id, product_id=product_id, entitled=True, rate_type="FLAT", price=50, starting_at="2024-01-01T00:00:00.000Z" ) ``` ```javascript Node theme={null} const rateCardResponse = await client.V1.contracts.rateCards.create({ name: "Language Model List Pricing", description: "Prices for all language models." }); const rateCardId = rateCardResponse.data.id; await client.contracts.rateCards.rates.add({ rate_card_id: rateCardId, product_id: productId, entitled: true, rate_type: "FLAT", price: 50, starting_at: "2024-01-01T00:00:00.000Z" }); ``` ```ruby Ruby theme={null} response = client.v1.contracts.rate_cards.create( name: "Language Model List Pricing", description: "Prices for all language models." ) rate_card_id = response.data.id response = client.v1.contracts.rate_cards.rates.add( rate_card_id: rate_card_id, product_id: product_id, entitled: true, rate_type: "FLAT", price: 50, starting_at: "2024-01-01T00:00:00.000Z" ) ``` ```go Go theme={null} rateCardResponse, err := client.V1.Contracts.RateCards.New(context.TODO(), metronome.ContractRateCardNewParams{ Name: metronome.F("Language Model List Pricing"), Description: metronome.F("Prices for all language models."), }) if err != nil { panic(err.Error()) } rateCardID := rateCardResponse.Data.ID startingTime, err := time.Parse(time.RFC3339Nano, "2024-01-01T00:00:00.000Z") if err != nil { panic(err.Error()) } _, err = client.V1.Contracts.RateCards.Rates.Add(context.TODO(), metronome.ContractRateCardRateAddParams{ RateCardID: metronome.F(rateCardID), ProductID: metronome.F(productID), Entitled: metronome.F(true), RateType: metronome.F(metronome.ContractRateCardRateAddParamsRateTypeFlat), Price: metronome.F(50.0), StartingAt: metronome.F(startingTime), }) if err != nil { panic(err.Error()) } ``` The properties used in this example include: * `entitled`, a boolean that indicates whether a rate shows up by default on a customer’s invoice. If `False`, it won’t appear on a customer’s invoice unless overridden at the contract level. * `rate_type`, used to configure how a rate gets applied as usage flows in. Supported values include `FLAT` or `TIERED`. * `price`, the rate itself. For USD, values are in **cents** (for example, `100` = \$1.00). Other currencies use whole units. See [currency denomination](/guides/pricing-packaging/make-pricing-changes/use-currency-custompricingunits#currency-denomination) for details. * `starting_at`, used to set the time when the rate goes into effect. To evolve your rates over time, set `starting_at` and `ending_before` dates to ensure smooth pricing updates. You can use this rate card for all SKUs across your product catalog. ## 6. Create a contract​ To start generating invoices for a customer, put them on a contract. A contract is an object that represents the terms a customer has agreed to pay, generally based on your rate card. At its most simple, a customer can have a basic contract where they pay the predefined list prices; this may cover many of your simple self-serve cases. If you have specific discounts or commits that a customer negotiated, configure these in the contract on top of the base list prices. Add your created customer to a contract, similar to this example that uses the Language Model List Pricing rate card: ```python Python theme={null} response = client.v1.contracts.create( customer_id=metronome_customer_id, rate_card_id=rate_card_id, starting_at="2024-08-01T00:00:00.000Z" ) ``` ```javascript Node theme={null} await client.V1.contracts.create({ customer_id: customerId, rate_card_id: rateCardId, starting_at: "2024-08-01T00:00:00.000Z" }); ``` ```ruby Ruby theme={null} response = client.v1.contracts.create( customer_id: metronome_customer_id, rate_card_id: rate_card_id, starting_at: "2024-08-01T00:00:00.000Z" ) ``` ```go Go theme={null} contractStartingTime, err := time.Parse(time.RFC3339Nano, "2024-09-01T00:00:00.000Z") if err != nil { panic(err.Error()) } contractResponse, err := client.V1.Contracts.New(context.TODO(), metronome.ContractNewParams{ CustomerID: metronome.F(customerID), RateCardID: metronome.F(rateCardID), StartingAt: metronome.F(contractStartingTime), }) if err != nil { panic(err.Error()) } contractID := contractResponse.Data.ID ``` After creating the contract, invoices get generated for all billing periods that occurred after the `starting_at` date. Usage data from the current period is visible to the `DRAFT` invoice. Line items on draft invoices update seconds after Metronome receives usage data. For the new contract from the example, the previously sent usage of 1 million tokens got applied. New contract Next, send in a few more usage events and see it update in real time: ```python Python theme={null} response = client.v1.usage.ingest( usage=[ { "transaction_id": "382a3069-d056-4249-824d-d288b51d7743", "timestamp": "2024-08-15T04:39:20Z", "customer_id": "team@example.com", "event_type": "language_model", "properties": { "model": "langModel4", "user_id": "johndoe", "tokens": 1000000 } }, { "transaction_id": "db64bf17-f13d-4c19-89cc-acaf878a42c6", "timestamp": "2024-08-16T19:11:02Z", "customer_id": "team@example.com", "event_type": "language_model", "properties": { "model": "langModel4", "user_id": "janedoe", "tokens": 5500000 } }, { "transaction_id": "266339fd-2125-4827-afb7-a395a7f0007f", "timestamp": "2024-08-17T12:51:32Z", "customer_id": "team@example.com", "event_type": "language_model", "properties": { "model": "langModel4", "user_id": "johndoe", "tokens": 3000000 } }, ] ) ``` ```javascript Node theme={null} await client.V1.usage.ingest([ { transaction_id: '382a3069-d056-4249-824d-d288b51d7743', timestamp: "2024-08-15T04:39:20Z", customer_id: 'team@example.com', event_type: 'language_model', properties: { model: "langModel4", user_id: "johndoe", tokens: 1000000 } }, { transaction_id: 'db64bf17-f13d-4c19-89cc-acaf878a42c6', timestamp: "2024-08-16T19:11:02Z", customer_id: 'team@example.com', event_type: 'language_model', properties: { model: "langModel4", user_id: "janedoe", tokens: 5500000 } }, { transaction_id: '266339fd-2125-4827-afb7-a395a7f0007f', timestamp: "2024-08-17T12:51:32Z", customer_id: 'team@example.com', event_type: 'language_model', properties: { model: "langModel4", user_id: "johndoe", tokens: 3000000 } }, ]); ``` ```ruby Ruby theme={null} response = client.v1.usage.ingest( usage: [ { transaction_id: "382a3069-d056-4249-824d-d288b51d7743", timestamp: "2024-08-15T04:39:20Z", customer_id: "team@example.com", event_type: "language_model", properties: { model: "langModel4", user_id: "johndoe", tokens: 1000000 } }, { transaction_id: "db64bf17-f13d-4c19-89cc-acaf878a42c6", timestamp: "2024-08-16T19:11:02Z", customer_id: "team@example.com", event_type: "language_model", properties: { model: "langModel4", user_id: "janedoe", tokens: 5500000 } }, { transaction_id: "266339fd-2125-4827-afb7-a395a7f0007f", timestamp: "2024-08-17T12:51:32Z", customer_id: "team@example.com", event_type: "language_model", properties: { model: "langModel4", user_id: "johndoe", tokens: 3000000 } } ] ) ``` ```go Go theme={null} err := client.V1.Usage.Ingest(context.TODO(), metronome.UsageIngestParams{ Usage: []metronome.UsageIngestParamsUsage{ { TransactionID: metronome.F("382a3069-d056-4249-824d-d288b51d7743"), Timestamp: metronome.F("2024-08-15T04:39:20Z"), CustomerID: metronome.F("team@example.com"), EventType: metronome.F("language_model"), Properties: metronome.F(map[string]interface{}{ "model": "langModel4", "user_id": "johndoe", "tokens": 1000000, }), }, { TransactionID: metronome.F("db64bf17-f13d-4c19-89cc-acaf878a42c6"), Timestamp: metronome.F("2024-08-16T19:11:02Z"), CustomerID: metronome.F("team@example.com"), EventType: metronome.F("language_model"), Properties: metronome.F(map[string]interface{}{ "model": "langModel4", "user_id": "janedoe", "tokens": 5500000, }), }, { TransactionID: metronome.F("266339fd-2125-4827-afb7-a395a7f0007f"), Timestamp: metronome.F("2024-08-17T12:51:32Z"), CustomerID: metronome.F("team@example.com"), EventType: metronome.F("language_model"), Properties: metronome.F(map[string]interface{}{ "model": "langModel4", "user_id": "johndoe", "tokens": 3000000, }), }, }, }) if err != nil { panic(err.Error()) } ``` After refreshing the invoice, the values from the three event payloads above applies to the running line item totals. The group keys previously applied let you separate out the invoice presentation by the user ID associated with the usage. Updated contract # Metronome Docs Source: https://docs.metronome.com/guides/get-started/home Understand the core parts of Metronome Get to your first invoice on Metronome What to keep in mind as you create your billing architecture # Build your pricing and packaging
Pay-as-you-go billing
Set up Metronome to support charging your customers in arrears for only what they use.
Metronome logo pointing at an invoice
Enterprise commits
Set up Metronome to support enterprise deal requirements like prepaid and postpaid commitments, negotiated discounts, one-time charges, contract renewals, and more.
Metronome logo pointing at an invoice
Subscriptions w/ usage
Set up Metronome to combine recurring revenue with usage-based components.
Metronome logo pointing at an invoice
Pre-paid credits
Set up Metronome to allow customers to purchase a batch of credits upfront, with auto-recharge or gated access when credits run out.
Metronome logo pointing at an invoice
# Get started with # How Metronome works Source: https://docs.metronome.com/guides/get-started/how-metronome-works At its core, Metronome transforms your customers' usage into precise, tailored invoices that reflect your unique business model. Let's start by looking at the end result — an invoice — and break down the building blocks that make it possible. Invoice Example: Multiple line items showing charges While simple invoices might seem to follow the basic formula **Price × Quantity = Charge** , modern usage-based billing requires a more sophisticated approach that includes a third critical element: your **Commercial Model**. Metronome's data architecture is built on three essential foundations - one for each part of this calculation: Metronome offering This comprehensive approach ensures you can not only calculate what customers owe but also encode how they should pay—whether through subscriptions, credits, commitments, or consumption-based billing. In the following sections, we'll explore each building block to show how Metronome's flexible architecture adapts to your evolving business needs. ## Quantity: Usage Tracking & Aggregation​ In usage-based billing, **quantity** represents how much your customers actually use your platform. Unlike traditional subscription models with fixed fees, usage-based billing requires accurately measuring customer activity — whether that's API calls made, data processed, storage consumed, or users onboarded. Metronome's approach to determining these quantities gives you exceptional flexibility through two key components: * [**Usage Events**](/guides/get-started/core-concepts/send-usage-events) capture the raw data about customer activity directly from your platform * [**Billable Metrics**](/guides/get-started/core-concepts/create-billable-metrics) transform this activity data into meaningful, billable quantities by defining both what to measure (filtering) and how to measure it (aggregation) ### Usage Events​ [Usage events](/guides/events/design-usage-events) are the raw data about how customers interact with your platform—API calls, storage consumption, user logins, or any measurable interaction. Metronome lets you design your own usage schema around your business needs. [Send usage events via our API](/guides/get-started/core-concepts/send-usage-events) in the format that makes sense for your operations, without conforming to rigid predefined structures. ### Billable Metrics​ [Billable metrics](/guides/get-started/core-concepts/create-billable-metrics/) transform raw usage events into meaningful quantities that appear on an invoice. They define how to meter, filter, and aggregate usage into billable units. Define exactly what you want to measure—from simple counts to complex aggregations with custom filters and groupings. One usage event can feed multiple billable metrics, giving you the flexibility to meter anything your customers use. Billable metrics filter and aggregate your event stream > **Strategic Insight:** By separating raw usage collection from billable metrics, you can evolve your metering model without changing how you instrument your application. Your engineering team simply instruments your application to send activity data, while your business team configures how to bill for it—all without additional code changes. ## Price: Products & Rate Cards​ While the quantity side of our equation deals with measuring usage, to configure the **price** for each metric, you must first define what you're selling and how much you charge for it. Metronome provides two components designed specifically for these tasks: * [**Products**](/guides/get-started/core-concepts/create-products-contracts) define what you're selling to customers * [**Rate Cards**](/guides/get-started/core-concepts/create-manage-rate-cards) establish how much you charge for those products ### Products​ [Products](/guides/get-started/core-concepts/create-products-contracts) define what you actually sell to customers—the individual SKUs that appear as line items on your invoices. Metronome supports multiple product types to accommodate different types of charges, including usage-based, fixed, or subscription charges. This ensures your product catalog represents everything you might charge for, not just usage-based items. Products for all charges on an invoice Your product catalog gives you control over both billing logic and presentation. You can: * **Customize invoice appearance** by determining how quantities are displayed, whether they're rounded, or how they're converted * **Organize related SKUs** using product tags for easier management and reporting * **Control granularity** by presenting charges as either a consolidated lump sum or itemized by specific dimensions This flexibility ensures your customers receive invoices that align with how they understand your value, rather than how your internal systems track usage. ### Rate Cards​ [Rate cards](/guides/get-started/core-concepts/create-manage-rate-cards) define the default pricing for your usage products across your entire customer base. Each rate includes what to charge per unit for specific start and end dates, enabling scheduled price changes, promotions, or gradual increases/decreases. Define your rate card in Metronome Through the rate card, Metronome decouples pricing from commercial models. This separation solves a key challenge in usage-based billing: maintaining consistent pricing while supporting diverse business arrangements. When you add a product to your rate card or update pricing, these changes automatically flow to all commercial models—whether customers are on subscriptions, consumption-based billing, or enterprise agreements. Contracts use rate cards to determine prices for a customer **Strategic Insight:** Most billing systems require you to duplicate product definitions across different plans and tiers, making pricing changes a time-consuming process that often results in inconsistencies and errors. Metronome's decoupled approach lets you define products once, price them once, and apply them across any commercial model. This gives you unprecedented agility to evolve your pricing strategy without spending weeks on implementation or disrupting your customers' experience. Many Metronome customers support *all* of their commercial models with just one rate card! ## Contracts: Encode Your Commercial Model​ With quantities measured and prices defined, the final element in our equation is your Commercial Model—how customers actually pay for what they use. This is where Metronome truly differentiates from traditional billing systems. Your commercial model must answer three essential questions: * **What** has the customer agreed to pay for? (products and rates) * **How** have they agreed to pay? (arrears, commitments, credits, subscriptions) * **Where** should they be charged? (payment systems and marketplaces) In Metronome, all these elements are defined in a **Contract**. ### Contracts​ [Contracts](/guides/get-started/core-concepts/provision-contract) connect customers to your pricing structure and define their specific commercial arrangement. Unlike rigid plan-based systems, Metronome contracts let you configure each aspect of the commercial relationship: * **Base Pricing** : Inherit standard rates from your rate cards * **Custom Terms** : Apply overrides like percentage discounts or custom per-unit pricing * **Product Access** : Enable or disable specific products for different customer segments * **Payment Structure** : Configure commitments, credits, or subscription fees * **Billing Cycles** : Determine invoice frequency and timing Pricing changes are inherited immediately This modular approach means you can support any commercial model your business requires: * **Pay-as-you-go** : Bill customers in arrears for their actual usage * **Prepaid Credits** : Sell credits upfront that draw down with usage * **Subscriptions with Overage** : Provide usage allowances with charges for exceeding thresholds * **Enterprise Commitments** : Secure minimum spend commitments with discounts * **Hybrid Models** : Combine any of these approaches for specific customer segments * And many more! Once a customer is on a contract, Metronome automatically starts to generate usage statements based on the defined parameters. If a customer has credits, we track utilization and drawdown. If they're on pay-as-you-go, they're charged at the end of their billing period. For commitments, we monitor actual usage against committed amounts. All elements of Metronome contracts are programmable via API, allowing you to build self-serve workflows, custom pricing pages, or enterprise quote-to-cash systems on the same foundation. **Strategic Insight:** Most billing systems force you to create rigid plan structures, where each combination of products and payment terms requires a separate plan. This approach breaks down as you scale—especially when you need to support both self-serve and enterprise customers on the same platform. Metronome's contract architecture decouples commercial models at the customer level, allowing each customer to have precisely the arrangement they need. This means you can run enterprise deals alongside self-serve customers without maintaining parallel billing systems or fragmenting your business logic across multiple codebases. ## Invoice Generation: Bringing It All Together​ When it's time to generate an invoice, Metronome: 1. **Receives usage data** from your events for the billing period 2. **Processes this data** through the appropriate billable metrics to calculate quantities 3. **Applies pricing** from the customer's contract, including any overrides from the base rate card 4. **Generates an invoice** that clearly communicates charges to your customer Metronome's dynamic invoice generation happens: * **Real-time with usage** - Every time usage is sent, Metronome evaluates [customer alerts and thresholds](/guides/customers-billing/set-up-notifications/create-and-manage-notifications) to send webhooks if spending limits are reached or credits are depleted * **On-demand via API** - Whenever the Metronome APIs are called, [powering real-time dashboards](/guides/customers-billing/optimize-customer-experience/customer-dashboards-and-reporting) in your end-user applications * **At billing cycle close** - When a customer invoice is finalized and [sent to your system of choice](/guides/invoices/overview), such as at the end of the month or quarter The invoice brings it all together ## Ready to Get Started?​ Follow the [API quickstart](/guides/get-started/api-quickstart) to begin setting up Metronome, or dive deeper with our detailed guides: * [Usage Events](/guides/events/design-usage-events) * [Billable Metrics](/guides/get-started/core-concepts/create-billable-metrics/) * [Products](/guides/get-started/core-concepts/create-products-contracts) * [Rate Cards](/guides/get-started/core-concepts/create-manage-rate-cards) * [Customers](/guides/get-started/core-concepts/provision-customer) * [Contracts](/guides/get-started/core-concepts/provision-contract) * [Packages](/guides/get-started/core-concepts/packages-overview) # Get to your first invoice Source: https://docs.metronome.com/guides/get-started/metronome-dashboard-quickstart This guide walks you through setting up billing, entirely in the Metronome dashboard. **Looking for the API guide?** If your engineering team is setting up Metronome programmatically, see the [API Quickstart](/guides/get-started/api-quickstart). **Don’t have a Metronome Account?** Sign up for a Sandbox account [here](https://signup.metronome.com/)! ## Step 1: Understand how the pieces fit together Before building anything, here's how Metronome's core objects connect: Metronome core objects Metronome separates *metering* (what you measure) from *rating* (what you charge). You can change pricing without changing your event instrumentation, and vice versa. Here's what each object does: * **Usage Events** — Raw records of customer activity sent to Metronome (e.g., "customer X used 1,500 input tokens on model gpt-5 at timestamp Z") * **Billable Metrics** — Rules that aggregate your events into billable quantities (e.g., "sum the `input_tokens` property for events of type `llm_request`"). This is also where you define **group keys** — the properties you'll use to price by or display on invoices. * **Products** — Named line items on an invoice. * **Rate Cards** — A centralized price book assigning a price to each product. A single rate card can be shared across many customers, making pricing updates easy to roll out. * **Contracts** — Customer-specific agreements referencing a rate card, defining the billing period, and optionally including credits, commits, or overrides. * **Packages** — Encodes your rate card and contract details in a single package to be applied across new customers. * **Invoices** — Automatically generated each billing period based on a customer’s recurring charges and usage, rated against the contract. **What you need to create (in this order):** 1. A billable metric 2. A product 3. A rate card with rates for each product 4. A customer 5. A contract linking the customer to the rate card Then you send events and Metronome handles the rest. ## Step 2: Know what you're measuring — event schema overview Before creating a billable metric, understand what your usage events will look like. See “[Design Usage Events](/guides/events/design-usage-events)” for full event schema details and payload examples. **Every event includes these required fields:** * **`transaction_id`** — Must be unique per event (used for deduplication) * **`customer_id`** — The Metronome customer UUID or an ingest alias * **`event_type`** — A string that connects the event to a billable metric (must exactly match) * **`timestamp`** — When the usage occurred **And optional properties (the key design decision):** * **`properties`** — Key-value pairs containing quantities to meter (e.g., `tokens_usage`), dimensions to price by (e.g., `model_name`, `region`), and metadata for invoice display or analytics (e.g., `user_id`, `project_id`, `cost`). Metronome supports up to **2,000 properties** per event. After creating a billable metric in the next step, you'll see an **example event payload** directly in the UI that shows you the expected format: Example event payload **TIP** Before creating a billable metric, decide which properties to include. The more metadata the better — properties like `user_id` (for seat billing), `region` (for regional pricing), `project_id` (for invoice breakdowns), and `cost` (for COGS analysis) are all valuable even if you don't use them on day one. ## Step 3: Create a billable metric A billable metric defines *what* to measure. Navigate to **Offering → Billable Metrics → + Add**. There are two billable metric types: * **Streaming Metric** — Covers most use-cases. Optimized for performance with real-time aggregation as events arrive. * **SQL Metric** — For complex calculations like daily averages, unique counts per period, or weighted formulas. [Learn more about SQL BMs →](/guides/get-started/core-concepts/billable-metrics-sql-editor) The following setup is for streaming billable metrics: 1. **Name** your metric (e.g., "Input Tokens"). 2. Set the **event type filter** — this must exactly match the `event_type` your application sends (e.g., `tokens_usage`). 3. Define properties. Include the property to use as the **aggregation key** (the property to aggregate, e.g., `num_tokens`). Send more properties than you think you need. You can always ignore unused properties, but you cannot retroactively add group keys to a billable metric. 4. Choose your **aggregation type**: | Type | What it does | Example use case | | ----- | ------------------------------------- | ----------------------------- | | Count | Counts matching events | API calls, requests, messages | | Sum | Sums a numeric property across events | Tokens, bytes, seconds | | Max | Maximum value in a window | Peak concurrent connections | 5. Select the group keys. ### Understanding group keys **Group keys** determine what you can price by and display on invoices downstream. Think of them like a `GROUP BY` clause in SQL — they break your aggregated usage into buckets. **What group keys enable (on the Product, in the next step):** | Downstream use | What it does | Example | | ---------------------- | ------------------------------------ | ------------------------------------------------------------ | | Pricing group key | Different prices per dimension value | `model_name` → charge \$1.50 for model-A, \$0.30 for model-B | | Presentation group key | Invoice line-item breakdowns | `user_id` → show per-user usage on invoice | **IMPORTANT: You must define group keys here on the billable metric first.** They cannot be added later, and they must exist here before they can be assigned as pricing or presentation keys on a product. **Common group key examples:** * `model_name` — per-model pricing (pricing group key) * `region` — per-region pricing (pricing group key) * `instance_type` — per-GPU/instance pricing (pricing group key) * `user_id` — per-user invoice breakdowns, or seat-based billing using the Unique aggregation (presentation group key) * `project_id` — per-project invoice breakdowns (presentation group key) **Billable metrics cannot be modified after creation** You cannot add or change group keys, property filters, or aggregation settings. If you think you *might* want to price by or display a dimension in the future, include it as a group key now. It is best practice to include all properties as group keys. 1. Define your **group keys** based on the guidance above. 2. **Review the event** in the Example event payload box to validate your filters. 3. Click **Save**. Navigate to **Offering → Billable Metrics**. Your new metric should appear in the list. Click into it to verify the aggregation, filters, and group keys are correct. ## Step 4: Create a product A **product** is a named line item that appears on your customer's invoice. Navigate to **Offering → Products → + Add new product**. 1. Enter a **Name** — this is what appears on the invoice (e.g., "Input Tokens"). 2. Select **Product Type**: * **Usage** — Variably priced based on customer usage (requires a billable metric) * **Subscription** — Recurring fee on a schedule (platform fees, seat licenses) * **Composite** — Percentage charge on a group of other products * **Fixed** — One-time or scheduled charges (used for commits, credits, one-time fees) * Commits vs Credits: Commits have a cost-basis, while credits are always free 3. For usage products, select the **billable metric** you created in Step 3. You can swap out the billable metric on a usage product if necessary. 4. Assign **group keys** on the product: | I want to... | Use | Example | | ------------------------------------------- | ---------------------- | ---------------------------------------- | | Charge different prices per dimension | Pricing group key | `model_name` → different price per model | | Show breakdowns on the invoice (same price) | Presentation group key | `user_id` → per-user line items | | One flat price for all usage | Don't set either | Simple count-based billing | You can use both pricing and presentation group keys on the same product (e.g., price by `model_name`, display by `user_id`). Group keys here must be a subset of the group keys on the underlying billable metric. *(Optional Conversions)* Add a **quantity conversion** — e.g., send individual tokens but display and price per million tokens on the invoice. Add a **rounding conversion** — e.g., send seconds but round and display to the nearest minute on the invoice. Navigate to **Offering → Products**. Click into your product to verify the billable metric and group keys. ## Step 5: Create a rate card A **rate card** is a centralized pricing table that assigns prices to your products. Rate cards are in a single fiat currency. Navigate to **Offering → Rate Cards → + Add new rate card**. **Best practice:** Use a single rate card as your source of truth for standard pricing. When you update rates here, changes propagate to all contracts that reference this rate card. You can override rates per-customer on individual contracts. 1. **Name** your rate card (e.g., "Standard Rate Card"). 2. **Add products** and set their rates. 3. If using **dimensional pricing** (pricing group keys on the product), define values for each dimension and set a rate per value. For example, if `model_name` is your pricing group key, add entries for `model-A` at \$1.50 and `model-B` at \$0.30. **Additional rate card features:** * **Tiered pricing** — Set volume-based tiers on any product. On the rate card, click into the product → Add Tiers. For example, first 1M tokens at \$1.00, next 1M at \$0.80. * **Custom Pricing Units (Credit Conversions)** — If you bill in credits or a custom unit rather than USD, first create a Custom Pricing Unit under **Offering → Pricing Units**, then configure the conversion on the rate card. [Learn more →](/guides/pricing-packaging/make-pricing-changes/use-currency-custompricingunits) * **Commit rates** — Set rates that apply specifically when usage draws down from a commit. * **Changing and Adding Rates** — Edit the rate to change the rate and select the start date of the new rate. Add new rates by clicking “Add a Rate” on the rate card. ## Step 6: Create a customer and contract Now tie everything together. ### Create a customer Navigate to **Customers → + Add customer.** Enter the customer **Name**. *(Optional)* Add **ingest aliases** so your engineering team can send events using your internal customer ID instead of Metronome's UUID. ### Create a contract Navigate to your new customer → **+ Add contract**. 1. Select your **rate card**. 2. Set the **contract start date and end date.** 3. *(Optional)* **Billing Provider** — Connect an invoice integration to send finalized invoices to a payment system. For details, see: * [Stripe Integration Guide](/integrations/invoice-integrations/stripe) * [AWS Marketplace](/integrations/marketplace-integrations/aws) / [Azure Marketplace](/integrations/marketplace-integrations/azure) 4. (Optional) **Include contract specific terms.** Contracts can include customer-specific terms, such as prepaid commits and overrides. See the following links for more information on setting this up. 1. [Credits and Commits](/guides/pricing-packaging/apply-credits-and-commits/create-a-pre-paid-commit) 2. [Overrides](/guides/customers-billing/manage-customers/provision-a-customer#add-contract-discounts-and-overrides) Navigate to **Customers → \[Your Customer] → Contract**. You should see the contract with your rate card assigned. ### Send test events (sandbox only) Now that you have a customer and contract, you can send test events directly from the UI. Navigate to the customer's contract view and click on the product on the rate card. You'll find the option to send test events here. Test events payload When composing a test event, keep in mind: * The **transaction\_id** must be unique for each event * The **timestamp** must be within the last 34 days * The **event\_type** and **properties** must match your billable metric's configuration (filters and group keys) This feature is only available in sandbox, not production. In production, your engineering team [sends events](/api-reference/usage/ingest-events) via the API. ## Step 7: Verify your invoice Metronome automatically generates invoices based on the billing schedule on the contract. **To see a draft invoice:** Navigate to **Customers → Contract → Invoices**. The current billing period's draft invoice should show your usage and calculated charges. **Invoice lifecycle:** 1. **Draft** — Accumulates usage throughout the billing period (viewable in Metronome). 2. **Finalized** — Locked at the end of the billing period. There is a **24 hour grace period** at the end of the billing period before invoices are finalized to make any necessary changes to an invoice. 3. **Sent to billing provider** — If connected (e.g., Stripe), invoices are pushed within \~1 hour of finalization. Payment status is managed in your billing provider's dashboard, not in Metronome. 4. **Paid / Failed** — Collection handled by your billing provider. You can set up [webhooks](/guides/platform-configuration/setup-webhooks#webhook-types) to listen to payment statuses for payment-gated commits. Verify the draft invoice shows correct usage quantities and charges based on your event ingestion and rate card pricing. If you see usage (under Events) but no charges on the invoice, check that your events are matching the pricing group key values on your rate card. ## Ready for more? You've created your first invoice in Metronome! Here are additional features to explore: * [**Embeddable Customer Dashboards**](/guides/customers-billing/optimize-customer-experience/customer-dashboards-and-reporting) — Give your customers self-serve visibility into usage and spend * [**Webhooks**](/guides/platform-configuration/setup-webhooks) — Get notified about invoice lifecycle events, balance thresholds, and payment outcomes * [**Alerts & Notifications**](/guides/customers-billing/set-up-notifications/create-and-manage-notifications) — Spend alerts, balance thresholds, usage milestones * [**Credits & Commits**](/guides/pricing-packaging/apply-credits-and-commits) — Prepaid balances, enterprise commitments, free tier credits * [**Revenue Recognition**](/guides/reporting-insights/financial-reporting/revenue-recognition) — ASC 606 / IFRS 15 compliance * [**Production Checklist**](/guides/implement-metronome/production-checklist) — When you're ready to go live # Manage contracts in Stripe Source: https://docs.metronome.com/guides/get-started/stripe-marketplace-app Use the Metronome Stripe App to create and manage usage-based contracts directly from the Stripe Dashboard. The app connects your Metronome account to Stripe, giving you a unified view of customers, revenue, and contracts without leaving Stripe. This guide describes how to install and set up the Metronome Stripe App, manage customers and contracts, and use the app's revenue dashboard. ## Prerequisites Before you begin, make sure you have: * A [Metronome account](https://signup.metronome.com) with at least one production environment configured * A Stripe account with access to the [Stripe Dashboard](https://dashboard.stripe.com) * The [Stripe integration](/integrations/invoice-integrations/stripe) configured in Metronome **INFO** The Metronome Stripe App manages contracts and customers through Metronome's interface embedded in the Stripe Dashboard. Invoicing still flows through Metronome's native Stripe integration. Set up the [Stripe invoicing integration](/integrations/invoice-integrations/stripe) first to ensure invoices created by your contracts reach Stripe. ## Install the app 1. Go to the [Metronome listing](https://marketplace.stripe.com/apps/metronome) on the Stripe App Marketplace. 2. Click **Install app** and follow the prompts. 3. After installation, the Metronome app is accessible from the Stripe Dashboard. ## Sign in to Metronome After installing the app, sign in to connect your Metronome account: 1. Open the Metronome app from the Stripe Dashboard. 2. Click **Sign in to Metronome**. 3. Complete the authentication flow. ## Overview dashboard The Overview tab provides a snapshot of your usage-based billing: * **Total revenue**: All-time billed amount across your Metronome contracts. * **Revenue last month**: Billed amount for the most recent billing period. * **Top products**: Your highest-revenue products, with remaining products grouped under "Other." * **Usage events**: A 30-day trend of [usage events](/guides/events/send-usage-events) ingested by Metronome, with separate series for total and duplicate events. * **Customers**: New customers added in the last month. The Overview tab also includes links to open the Metronome app and Metronome documentation. ## Manage customers The Customers tab displays all Stripe customers that are linked to Metronome customers. For each customer, the app shows: * **Date created**: When the customer was added based on the Stripe creation date. * **Lifetime billings**: Total amount billed to the customer. * **Provision status**: The state of the customer's contracts — Active, Active Soon, or Recently Ended. From any customer row, you can: * **View Customer** in Stripe to see their full Stripe profile. * **Manage in Metronome** to open the customer in the Metronome dashboard for advanced configuration. * **Create Contract** to start the contract creation flow for that customer. If a Stripe customer is linked to multiple Metronome customers, the **Manage in Metronome** and **Create Contract** actions expand into sub-menus so you can select which Metronome customer to act on. ### Customer detail view When you view a Stripe customer's detail page, the Metronome module displays all [contracts](/guides/get-started/core-concepts/provision-contract) linked to that customer. Each contract shows the contract name (falling back to the rate card name if unnamed), the contract period with an "(Active)" indicator when applicable, and the products included in the contract. If the Stripe customer does not yet have a corresponding Metronome customer, the app automatically [creates one](/guides/get-started/core-concepts/provision-customer) using the Stripe customer name when you initiate contract creation. ## Create a contract The contract creation flow is a four-step wizard that guides you through building a usage-based [contract](/guides/get-started/core-concepts/provision-contract). ### Step 1: Invoicing Configure the core contract terms: * **Contract name**: A descriptive name for the contract. * **Start date**: When the contract begins. Defaults to today. * **End date** (optional): When the contract ends. Leave blank for open-ended contracts. * **Invoice schedule**: How often [usage invoices](/guides/get-started/core-concepts/how-invoicing-works) are generated — Monthly, Quarterly, Annual, or Weekly. * **Send on**: When invoices are sent — the 1st of the month or the contract start date. * **Net payment terms**: The number of days a customer has to pay after an invoice is issued. Defaults to 30. ### Step 2: Pricing Select a rate card and optionally customize pricing for this contract: * **Rate card**: Choose from your configured Metronome [rate cards](/guides/get-started/core-concepts/create-manage-rate-cards). The rate card defines the base pricing for all products on the contract. * **Price overrides**: Apply discount percentages to specific products, scoped by [product tags](/guides/get-started/core-concepts/create-products-contracts) and date range. **TIP** You can see which products have which product tags by hovering over their name in the table. * **Subscription quantities**: If the rate card includes subscription products, set the initial quantity for each subscription line item. * **Prices**: After selecting a rate card, view a summary of all products and their effective prices, including any overrides applied. You can check or uncheck individual products to override their entitlement on this contract. **TIP** To set discounts, your products must have [product tags](/guides/get-started/core-concepts/create-products-contracts) configured in Metronome. If multiple tags are selected, the override applies only to products that have **all** of the selected tags. ### Step 3: Credits Add [credits](/guides/pricing-packaging/apply-credits-and-commits/create-a-pre-paid-commit) to the contract. * **Credit**: The name that will be used on the invoice line item when this credit is applied. (This comes from a Fixed Product defined in Metronome.) * **Applicable product tags** (optional): Restrict which [products](/guides/get-started/core-concepts/create-products-contracts) can draw from this credit. If omitted, all usage products on the contract consume the credit. * **Schedule**: How \[credits]\(/guides/pricing-packaging/apply-credits-and-commits/create-a-pre-paid-commit) are allocated: * **One-time**: A single allocation with a start date and end date. * **Monthly**: A recurring allocation with a start date and optional end date. * **Custom**: Multiple segments, each with its own start date, end date, and amounts. * **Invoice amount**: What the customer is charged for the credit. * **Credit amount**: The usage amount the customer receives. ### Step 4: Confirmation Click **Create contract** to finalize. The contract is created with the Stripe customer's existing billing provider configuration, so invoices flow to Stripe automatically. ## Troubleshooting ### Authentication errors If you see "There was an error signing in to Metronome," try these steps: 1. Go to the app **Settings** page and click **Clear cached Metronome credentials** under Developer settings. 2. Go to [app.metronome.com](http://app.metronome.com)/logout and log out. 3. Navigate back to the Metronome Stripe App and click “Sign in” ### Missing customers The Customers tab only displays Stripe customers that have a corresponding Metronome customer linked via the Stripe billing configuration in the currently connected Metronome account. If a customer doesn't appear: * Verify you are logged in to the correct Metronome account. * See Authentication errors above to sign out and sign back in * Verify the customer exists in Metronome with a Stripe billing configuration. * Confirm the `stripe_customer_id` in the Metronome billing configuration matches the Stripe customer ID. ### Stripe account not linked If you see "The Metronome account you've connected is not linked to this Stripe account," the Stripe integration has not been configured in your Metronome environment. Set up the [Stripe invoicing integration](/integrations/invoice-integrations/stripe) in Metronome before using the app. For persistent issues, contact us via the [Metronome support portal](https://support.metronome.com/). # Create streaming billable metrics Source: https://docs.metronome.com/guides/implement-metronome/core-concepts/billable-metrics-basic-filters The streaming`Basic Filters` editor is a structured query builder designed to provide out-of-the-box filters and aggregations on your usage stream. All metrics defined with the Basic Filters editor are created as streaming billable metrics. Billable metrics can be created in both the [Metronome app](https://app.metronome.com/) or using the [Metronome API](/api-reference/billable-metrics/create-a-billable-metric). For this example, create a metric to track "API Calls" for a hypothetical cloud service. 1. Navigate to the Billable Metrics section in Metronome. 2. Click `+ Add new Billable Metric`. 3. Choose `Basic filters`. 4. Name your metric (for example, `API Calls`). 5. Select the event type (for example, `api_request`). 6. Set filters: * **Property 1** * `property_name`: "status" * `operator`: "In" * `value`: "success" (This ensures Metronome only counts successful API calls.) * **Property 2** * `property_name`: "user\_id" * `operator`: "Exists" * (Metronome uses this as a group key to display API calls broken out by user.) 7. Choose the aggregation method: * To count the number of API calls, not sum or average them, select "Count". Streaming billable metrics support four aggregation types: `COUNT`, `SUM`, `MAX`, and `LATEST`. For other aggregation types, such as `UNIQUE`, use a [SQL billable metric](/guides/implement-metronome/core-concepts/billable-metrics-sql-editor). 8. Set a group key for `user_id`. 9. Review and save your metric. Billable metric creation flow This billable metric counts all successful API calls broken out by `user_id`, providing a simple but effective measure of platform usage across an organization. Prefer using the API? Here is an example request to set up the same metric: ```bash theme={null} curl -X POST https://api.metronome.com/v1/billable-metrics/create \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "name":"API Calls", "event_type_filter": { "in_values": ["api_request"] }, "property_filters": [ { "name": "status", "exists": true, "in_values": ["success"] }, { "name": "user_id", "exists": true } ], "aggregation_type": "COUNT", "group_keys": [["user_id"]] }' ``` # Create SQL billable metrics Source: https://docs.metronome.com/guides/implement-metronome/core-concepts/billable-metrics-sql-editor Billable metrics defined using the SQL Editor are formatted as SQL queries that are run against a table called `events`, which includes all of the raw usage events that are sent in to Metronome. Similar to the Basic Filters editor, billable metric SQL queries should include a set of filters that identify the correct usage events to query over, and an aggregation to turn these events into a value that Metronome will use as the quantity for downstream line items. Metronome handles filtering down the SQL queries for individual customers over the course of their billing period. You do not need to include this logic in your queries - simply focus on filtering and aggregation! ## Supported features and functionality​ Here is how you can access elements of your usage event within the query: * Query the `events` table * You can access the event\_type field in the SQL editor by using `event_type` * You can access the timestamp field in the SQL editor by using `timestamp` * You can access any fields in the properties dictionary by using `properties.field_name` If your query returns more than one column, Metronome first looks for a column called `value` to use as the column for the metric quantity. If no column `value` exists, Metronome uses the first column returned in the query. Any other columns returned can be used as group keys in downstream pricing and packaging. **INFO** If extra columns are returned but are not used as presentation or pricing group keys, Metronome sums over all of the results to generate a single quantity for the metric. ## Supported functions and operators​ The SQL Editor supports these functions and operators. * **Aggregations** * `COUNT`: Counts the number of rows * `SUM`: Sums numbers * `MAX`: Takes the maximum of numbers * `MIN`: Takes the minimum of numbers * `AVG`: Averages numbers * `EARLIEST`: Returns the earliest value of a column based on its `timestamp` * `LATEST`: Returns the latest value of a column based on its `timestamp` * `COUNT DISTINCT`: Counts the distinct values in the expression * **Math** * `+`, `-`, `*`, `/` * `=`, `!=`, `>`, `<`, `≥`, `≤` * `LEAST`: Returns the least of its arguments * `GREATEST`: Returns the maximum of its arguments * `ROUND`: Rounds a number to a specified number of decimal places * `CEIL`: Returns the smallest integer value that is greater or equal to the input * `FLOOR`: Returns the largest integer value that is less than or equal to the input * **Logic** * `AND` * `OR` * `NOT` * `CASE WHEN` * `IS NULL` * `IS NOT NULL` * `IN` * `NOT IN` * `=` * `!=` * **Dates** * `DATE_TRUNC`: Truncates the `timestamp` field to the `hour` or `day`. * **Casting** * `CAST` ## Example creation flow​ As an example of a more complex scenario, use the SQL Editor to create billable metric that tracks the daily average of storage used over a billing period. 1. Navigate to the Billable Metrics section in the [Metronome app](https://app.metronome.com/). 2. Click `+ Add new Billable Metric`. 3. Choose `SQL query`. 4. Name your metric (for example, `Storage latest daily max`). 5. Enter your SQL query: ```sql theme={null} SELECT SUM(max_daily_storage) / SUM(num_days) as value, user_id, region FROM ( SELECT date_trunc('day', timestamp) as date, properties.user_id as user_id, properties.region as region, MAX(properties.storage_used) as max_daily_storage, 1 as num_days FROM events WHERE event_type = 'storage_heartbeat' GROUP BY date, user_id, region ) GROUP BY user_id, region ``` **INFO** In this example, `user_id` is returned so that it can be defined as a `presentation_group_key` when creating a product from this metric. This allows you to display invoices broken out by `user_id`. `region` is returned so that it can be defined as a `pricing_group_key`. This would allow you to add different rates for this billable metric for values of `us-east-1`, `us-west-1`, or `ap-south-1`. 6. Preview your metric against any existing usage data to ensure the results are correct. When complete, save your metric. ## SQL breakdown granularity When you create a Product backed by a SQL billable metric, you can select a SQL breakdown granularity. The default value is `hour`, which is appropriate for most use cases. With `hour` granularity, costs are incurred continuously throughout the billing period as usage is ingested. If you want to use the latest value of a metric, or otherwise have a metric that does not make sense when broken down hourly, you can use `service period`. ## Example Let's walk through a simple example to compare the two granularities. Imagine you have a simple SUM metric built using a SQL billable metric. On day 1 of the customer's billing period, you send in a value of 5. On day 2, you send in a value of 10. On day 3, you send in a value of 15. The customer's billing period spans from 1/1/2026 to 2/1/2026. With the default `hour` breakdown granularity, costs are incurred as usage is ingested: * Assuming you schedule that the rate is \$10 from 1/1/2026 to 1/15/2026, and the rate is \$20 from 1/15/2026 onward, all three events will be priced at \$10. * If you created a credit or commit that applied only to day 2 of the billing period, only the usage value of 10 and corresponding spend of \$100 would apply against the credit or commit. * When using the `invoice-breakdowns` endpoint, you would see a value of 5 with a total of \$50 incurred on day 1, a value of 10 with a total of \$100 incurred on day 2, and a value of 15 with a total of \$150 incurred on day 3. If you instead set the SQL breakdown granularity to `service period`, the full quantity of 30 uses will be incurred at the last time window of the billing period: * The final price for the billing period will be used for the full quantity. For example, if you schedule that the rate is \$10 from 1/1/2026 to 1/15/2026, and the rate is \$20 from 1/15/2026 onward, the full quantity of 30 will be priced at \$20. * Credits and commits must cover the last instant of the billing period to apply against the spend. * When using the `invoice-breakdowns` endpoint, the costs will be incurred in the last time window of the billing period. ## Scheduling a change to or from a SQL billable metric on the Contract Product If you want to change the metric you're using to bill your customers, you can schedule a change to the billable metric associated with a usage product. SQL billable metrics are swappable on products, and the swap can be scheduled to take effect at any point in a billing period — not only at a billing period boundary. Let's walk through an example where we switch from Billable Metric A to Billable Metric B, both SQL billable metrics, as of 3/15/2026. Assume that the client is using 1st-of-the-month billing. * Billable metric A takes the `avg` over the field `value` for events that match `average_metric_v1`. * Billable metric B takes the `avg` over the field `value_new` for events that match `average_metric_v2`. We have some usage events that match these billable metrics: * On 3/1/2026, an event with a `value` of 4 is ingested, with an event type `average_metric_v1` * On 3/2/2026, an event with a `value` of 6 is ingested, with an event type `average_metric_v1` * On 3/15/2026, an event with a `value_new` of 10 is ingested, with an event type `average_metric_v2` * On 3/16/2026, an event with a `value_new` of 12 is ingested, with an event type `average_metric_v2` In the billing period of the update, during the period before the billable metric update is scheduled, we use only Billable Metric A: * On 3/1/2026, a quantity of 4 is incurred with its corresponding cost. * On 3/2/2026, the average of 4 and 6 is 5. A quantity of 4 was already incurred on Day 1, so an additonal quantity of 1 is incurred with its corresponding cost. In the billing period of the update, after the billable metric update, we use a formula to determine what the value of the combined metric is on each day: * Billable Metric B's value, using all of the event data for the period up to the current day * plus Billable Metric A's value, using all of the event data until the day of the swap * minus Billable Metric B's value, using all of the event data until the day of the swap This means with the above example: * On 3/15/2026, a quantity of 10 is incurred with its corresponding cost. * On 3/16/2026, the average of 10 and 12 is 11. A quantity of 1 is incurred with its corresponding cost. Note that the third part of the formula, Billable Metric B's value using all of the event data until the day of the swap, is 0 in this case because the two earlier events do not match Billable Metric B. # Create billable metrics Source: https://docs.metronome.com/guides/implement-metronome/core-concepts/create-billable-metrics A billable metric is a customizable query that filters and aggregates events from your event stream. These metrics are tracked continuously as usage enters Metronome through the ingestion pipeline. The ingestion process transforms raw usage data into actionable pricing metrics, enabling you to accurately meter and bill for your products. This is what is ultimately used to calculate the *quantity* for invoice line items, and can be used for alerts. Billable metrics are a foundational piece of the pricing model within Metronome. Once billable metrics are created, they contribute to an invoice as follows: * Billable metrics are associated with [products](/guides/get-started/core-concepts/create-products-contracts), which is where you set the presentation layer for how line items should be displayed on an invoice. * List prices are defined for products as rates on a [rate card](/guides/get-started/core-concepts/create-manage-rate-cards). * Rates can be associated or overwritten on a [contract](/guides/get-started/core-concepts/provision-customer), which is where invoices are generated for each Metronome customer. Quantities for each of the line items are calculated from events using the billable metric definition. Implementing billable metrics in Metronome involves these steps: 1. Identify usage components to price on. 2. Identify the desired scale and latency needed for invoice calculations. 3. Define `Group keys` to organize your metric data. 4. Define filters and an aggregation strategy to identify and accumulate relevant events from your usage stream. ## 1. Identify usage components​ Before implementing your billable metrics, determine the factors that contribute to your usage-based billing. You should consider what aspects of your service your customers value most, what they would expect to see on a final invoice, and what data elements you have available to send to Metronome. Some example metrics may include: * Number of API calls * Number of input and output tokens consumed * Storage used (GB hours) * Number of users Designing billable metrics goes hand-in-hand with designing usage events. While your usage events may include a number of relevant properties that you may want to price on, your billable metrics should individually align to the component that you may want to meter. For example, your usage event could be a heartbeat from a server that contains CPU utilization, memory used, and cloud region. If you would like each of these usage components to contribute to a user’s pricing, create separate metrics to aggregate the value from each property. Usage components For more information on what to consider before designing your usage events, please review our [Design usage events](/guides/events/design-usage-events) guide. ## 2. Identify desired scale and latency​ Before implementing your billable metrics, consider the scale of events that you send to Metronome for a particular metric. Metronome offers two types of billable metrics: * **Streaming billable metrics** : metrics designed for ultra low latency and high throughput workflows. Use Streaming billable metrics if: * Your metric definitions can be defined through a set of simple filters and aggregations (e.g. `COUNT`, `SUM`, `MAX`, or `LATEST`). * You require real-time [alerting](/guides/customers-billing/set-up-notifications/create-and-manage-notifications) across a wide customer base with a high event volume. ### Streaming billable metric aggregation types Streaming billable metrics support four aggregation types: `COUNT`, `SUM`, `MAX`, and `LATEST`. All four are available everywhere—UI, API, Plans, and Contracts. `LATEST` returns the most recent value for the property within the billing period—useful for metrics where you want to bill on a point-in-time reading (for example, the latest reported seat count or storage size) rather than a sum or max across the period. `LATEST` metrics can be used with group keys, but cannot currently be used with contract-level usage filters. See [Usage filters](/guides/customers-billing/manage-customers/provision-a-customer#create-a-usage-filter) for details. If you need to count distinct values (for example, unique users), use a [SQL billable metric](/guides/implement-metronome/core-concepts/billable-metrics-sql-editor) with `count(distinct …)`. **INFO** When using streaming billable metrics, the billable metric must be defined in Metronome before any usage can be associated with it. If usage is sent before a streaming metric is defined, it isn't attributed to the metric by default. Since Metronome retains all raw events received, we can perform a reflow if you ever need past events to apply to a new streaming billable metric — contact us via the [Metronome support portal](https://support.metronome.com/) to request a reflow. * **SQL billable metrics** : metrics designed with SQL queries to support more complex calculations. * Used if the desired billable metrics are not satisfied by the basic filters provided in streaming billable metrics. **INFO** For many alerting workloads, SQL billable metrics will have comparable performance to streaming billable metrics. For complex queries or high numbers of SQL billable metrics, we can help provide guidance to achieve desired latency. Please contact us via the [Metronome support portal](https://support.metronome.com/) if you are interested in using SQL billable metrics with alerts. ## 3. Define group keys​ `Group keys` are used in Metronome to specify one or more properties that can be used to break out usage in downstream pricing and packaging. This functions similarly to a `group by` clause in a SQL query. Group keys must first be defined in the metrics layer in order to be available to use in downstream pricing and packaging. A given billable metric can have many group keys. Group keys help support the following use cases in the platform: * **Presentation group keys** allow you to separate out quantities on an invoice by a particular property value. * For example, if you specify `user_id` as a group key, you can display usage on an invoice broken out by each `user_id` . This is useful for attributing spend across a larger organization. * **Pricing group keys** form the basis for [dimensional pricing](/guides/get-started/core-concepts/create-manage-rate-cards#dimensional-pricing%E2%80%8B) and allow you to price a metric differently based on property values. * For example, if you specify properties `[cloud_service_provider, region]` as a group key, you can set up separate rates for events with different values of this property. * Events with properties `cloud_service_provider=aws` and `region=us-east-1` are priced at \$0.50 * Events with property `cloud_service_provider=azure` and `region=southindia` are priced at \$0.40 If you create a product that uses both presentation and pricing group keys, you need to define all of the properties across both keys in one compound group key. For instance, if you want a product to support both of the examples above—presentation group key on `user_id` and pricing group key on `[cloud_service_provider, region]` , create a group key on the billable metric that looks like `[user_id, cloud_service_provider, region]` . **CONFIGURATION NOTE** Using group keys with many possible values for a given customer can increase latency when calling the Metronome API. If you anticipate the cardinality of these possible values reaching one thousand, contact us via the [Metronome support portal](https://support.metronome.com/) to discuss your configuration. ### Define group keys on streaming billable metrics​ Group keys for streaming billable metrics are defined through the basic filters editor, or through the [create billable metric](/api-reference/billable-metrics/create-a-billable-metric) API endpoint. To include a property in a group key, it must be first defined in the property filters with an `Exists` or `In` filter. Group keys are not editable once a metric is created, so it is important to consider if they are needed for your invoice presentation or pricing when creating your billable metrics. ### Define group keys on SQL billable metrics​ When defining a SQL billable metric, any property returned by your SQL query outside of the `value` column can be used as a group key. For example, to use the property `user_id` as a presentation group key, and `region` as a pricing group key, your SQL query may look like: ```sql theme={null} SELECT count() as value, properties.user_id, properties.region FROM events WHERE event_type = 'api_request' GROUP BY user_id, region ``` ## 4. Define filters and aggregations for relevant events​ Once you have the pricing elements from your usage stream that you would like to see represented in Metronome, you must implement your billable metric definition. Metronome offers two tools for defining Billable Metrics: * [Basic Filters editor](/guides/get-started/core-concepts/billable-metrics-basic-filters/) A user-friendly interface with predefined filters and aggregations, suitable for most basic use cases. **INFO** All metrics created with the Basic Filters editor are created as streaming billable metrics. * [SQL Editor](/guides/get-started/core-concepts/billable-metrics-sql-editor/) A more flexible option allowing custom SQL queries for complex scenarios. All metrics created with the SQL editor are created as SQL billable metrics. ## 5. Send and trace events to test your billable metric​ Once you've created your billable metric, send some events to make sure they are correctly matching as expected. Use the [ingest](/api-reference/usage/ingest-events) endpoint to send your test events, then call the [searchEvents](/api-reference/usage/search-events) endpoint with the events' `transaction_ids`. The response contains the list of matched billable metrics, as well as the matched customer if it exists. If you've set up a matching customer and matching billable metric, but do not see these values populated, you can dig into the billable metric definition to see if anything is incorrectly defined. # Create and manage rate cards Source: https://docs.metronome.com/guides/implement-metronome/core-concepts/create-manage-rate-cards Rate cards provide a centralized vehicle to store and update pricing information for your products in Metronome. This includes the ability to encode today’s standard rates and schedule changes in the future. Given its role as the source of truth for pricing, all Metronome contracts are built on top of rate cards. Aggregating this information in one entity enables you to quickly implement pricing changes for all customers whose contracts reference it. Diagram showing where rate cards fit in the Metronome data model ## How rate cards work​ Rate cards represent your standard pricing rates. Beyond those standard rates, overrides on the rate card enable you to configure flexible discounting by any custom dimension, such as region, service type, and model type. For example, AI research companies commonly use a pricing pattern to charge by token used in queries to individual LLM models. These companies can charge different rates for different types of customers, like PayGo or enterprise. Additionally, they might offer premium models to enterprise customers and limit PayGo to legacy models. In Metronome, they could design these two options by creating two distinct rate cards or by managing a single rate card that represents the standard listing with configured overrides for enterprise contracts. ## Prerequisites​ Before setting up a rate card, you need products in Metronome. Products serve as the base entity to price on. Given this dependency, create your [products](/guides/get-started/core-concepts/create-products-contracts) in Metronome before moving on to pricing. ## Create a rate card​ You can create a rate card with the Metronome app or API. ### Create a rate card via UI​ To create a rate card in the [Metronome app](https://app.metronome.com/products), go to Offering → Rate cards → click **Add new rate card** : 1. Give the rate card an internally meaningful **Name** (for example, *Enterprise Price Book - 2024*). 2. Add an optional **Description** (for example, *Standard pricing from October 2024 – July 2025*). 3. Optionally **Add aliases**. Aliases can be used in place of the Metronome-generated rate card IDs when provisioning contracts via API. **TIP** Rate card aliases help maintain the integrity of API integrations while switching the underlying rate card associated with the integration. This allows for more flexibility to overhaul your pricing and packaging while maintaining your integration infrastructure. 4. Select the products to add to the rate card. 5. Choose the rate card's fiat currency. Each rate card is associated with one fiat currency. The default is USD. 6. Define the rates, default entitlements, and effective dates for each product. 7. Review the rate card and click **Save** to create the completed card. Rate card example ### Create a rate card via API​ To create a rate card with the API, make a POST request to the [/contract-pricing/rate-cards/create](/api-reference/rate-cards/create-a-rate-card) endpoint: This example shows how to generate a rate card that has two different aliases with start and end dates. ```bash theme={null} curl https://api.metronome.com/v1/contract-pricing/rate-cards/create \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "name": "Rate Card Sample", "description": "Rate Card Sample", "aliases": [ { "name": "Sample Alias - Customer Workflow 1", "starting_at": "2024-01-01T00:00:00.000Z", "ending_before": "2025-01-01T00:00:00.000Z" }, { "name": "Sample Alias - Custom Workflow 2", "starting_at": "2025-01-01T00:00:00.000Z", "ending_before": "2026-01-01T00:00:00.000Z" } ] }' ``` To add rates with the API, make a POST request to the [/contract-pricing/rate-cards/addRates](/api-reference/rate-cards/add-a-rate) endpoint. This example shows how to create two rates for usage-based products that leverage pricing group keys. These rates make use of the same product, but show pricing variation between regions. ```bash theme={null} curl https://api.metronome.com/v1/contract-pricing/rate-cards/addRates \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "rate_card_id": "d7abd0cd-4ae9-4db7-8676-e986a4ebd8dc", "rates": [ { "product_id": "13117714-3f05-48e5-a6e9-a66093f13b4d", "starting_at": "2024-01-01T00:00:00.000Z", "entitled": true, "rate_type": "FLAT", "price": 100, "pricing_group_values": { "region": "us-west-2", "cloud": "aws" } }, { "product_id": "13117714-3f05-48e5-a6e9-a66093f13b4d", "starting_at": "2024-01-01T00:00:00.000Z", "entitled": true, "rate_type": "FLAT", "price": 120, "pricing_group_values": { "region": "us-east-2", "cloud": "aws" } } ] }' ``` ## Update a rate card​ After creation, you have two options for updating the rate card: edit the rate card metadata or schedule a rate change. ### Edit rate card metadata​ When editing the rate card metadata, you can: * Change the rate card name * Change the rate card description * Add or remove rate card aliases * Rate new products on your rate card To edit the rate card metadata, go to the specific rate card from the **Offering** > **Rate Cards** page or make a POST request to [/contract-pricing/rate-cards/update](/api-reference/rate-cards/update-a-rate-card). ### Schedule a rate change​ Scheduling a price change is a common workflow for organizations. In traditional billing systems, this process can require significant cross-functional coordination to ensure the change takes place at the right moment. Metronome streamlines this process by allowing you to schedule changes for a specified time period. For example, if you know you’re launching a product next month, you can schedule a rate change to go into effect on the launch day. On the day your rate changes take place, you can focus on your customers, not on their billing configuration. To schedule a rate change through the API, make a POST request to [/contract-pricing/rate-cards/addRates](/api-reference/rate-cards/add-a-rate). This is the same endpoint used to create new rates. The example below uses the same API call as the prior example, however, it adds two important additions: a `starting_at` date set for one year after the initial pricing and the updated price. ```bash theme={null} curl https://api.metronome.com/v1/contract-pricing/rate-cards/addRates \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "rate_card_id": "d7abd0cd-4ae9-4db7-8676-e986a4ebd8dc", "rates": [ { "product_id": "13117714-3f05-48e5-a6e9-a66093f13b4d", "starting_at": "2025-01-01T00:00:00.000Z", "entitled": true, "rate_type": "FLAT", "price": 120, "pricing_group_values": { "region": "us-west-2", "cloud": "aws" } }, { "product_id": "13117714-3f05-48e5-a6e9-a66093f13b4d", "starting_at": "2025-01-01T00:00:00.000Z", "entitled": true, "rate_type": "FLAT", "price": 140, "pricing_group_values": { "region": "us-east-2", "cloud": "aws" } } ] }' ``` ## Dimensional pricing​ Cloud-based companies seeking to align their COGS with pricing strategies commonly adopt dimensional pricing. For these companies, the product may cost a variable amount depending on its configuration. Dimensional pricing helps you set a product’s rate across multiple dimensions (cost drivers) without creating new product entities. You can define these dimensions by pricing [group keys](/guides/get-started/core-concepts/create-billable-metrics#3-define-group-keys%E2%80%8B) on the underlying product. ### How dimensional pricing works​ The dimensional pricing structure simplifies the management of products and billable metrics by minimizing the amount of each required to represent your business’s pricing scheme. The relationship between rates and the underlying objects looks like this: **Traditional Metronome object relationship:** 1 billable metric → 1 product → 1 rate **Dimensional pricing object relationship:** 1 billable metric → 1 product → many rates To further explain dimensional pricing, consider an example infrastructure SaaS client. This client has 3 products: reads, writes, and data storage. Traditionally, a single product would get a single price. Instead, for this client, rates are based on four additional dimensions: * Cloud provider: AWS, Azure, or GCP * Zone: na, emea, apac, or sa * Classification: basic, premium, or platinum * Number of cloud availability zones: 3 or 1 To determine how many total rates the client has, multiply the number of products by each of the possible values for each group: 3 cloud providers \* 4 zones \* 3 classifications \* 2 availability zones \* 3 products = 216 combinations that could need distinct prices. This pricing model is advantageous for the example infrastructure company given price variability across dimensions. AWS, Azure, and GCP may charge them different rates depending on the region. Using dimensional pricing in Metronome, they only need to manage three products and billable metrics by instead relying on the grouping keys (for example, cloud provider) for each. For help determining if dimensional pricing is right for your business model, contact us via the [Metronome support portal](https://support.metronome.com/). ### Set up dimensional pricing​ Set up a rate card with dimensional pricing in the Metronome app or with the API. To set up dimensional pricing in the Metronome app: 1. Create a new rate card and choose product(s) to add. Ensure that the products you're adding have [pricing group keys](/guides/get-started/core-concepts/create-products-contracts#pricing-group-keys%E2%80%8B) defined. 2. Define the potential values present across each pricing key dimension. For example, if the dimension is `aws_region`, define each possible region. 3. Assign rates to each combination of pricing group keys. To set dimensional prices with the API, make a POST request to the [/contract-pricing/rate-cards/addRates](/api-reference/rate-cards/add-a-rate) endpoint. ## Tiered pricing​ Tiered pricing is a usage-based pricing model where the rate applied depends on the quantity used so far in the billing period. For example, a rate card for a cloud database product might dictate that the first thousand gigabytes of data cost \$0.10 per gigabyte, and every gigabyte thereafter costs \$0.09. Or, another product might offer a free tier up to a usage limit, then charge for usage past that limit. ### How tiered pricing works​ You can define tiers when creating a rate card or as an [override](/guides/pricing-packaging/make-pricing-changes/edit-or-override-a-contract) on a contract. On contract overrides you can change the tier boundaries or price assigned to each tier for a specific customer. When you configure tiered pricing on a rate card, the minimum usage value is exclusive and the maximum usage value is inclusive. Consider an example communications client with a long distance phone call product. This product has three pricing tiers: the first 5 uses are free, uses 6-10 are \$1 each, and uses 11 and above are \$1.50 each. Their tiering rate in the Metronome app looks like this: | Minimum | Maximum | Value | | ------- | ------- | ----- | | 0 | 5 | \$0 | | 5 | 10 | \$1 | | 10 | ∞ | \$1.5 | **INFO** You only need to set up tiered pricing once for a product with [presentation group keys](/guides/get-started/core-concepts/create-products-contracts#group-keys%E2%80%8B). Metronome automatically applies tiers per presentation group value. For example, if a client uses `project_id` as a presentation group key on product X, setting a tiered rate on product X automatically applies per `project_id`. Invoices for tiered products group charges by tier and reflect each tier as a separate line item. ### Set up tiered pricing​ Set up a rate card with tiered pricing in the Metronome app or with the API. To set up tiered pricing in the Metronome app: 1. Create a new rate card and choose the product(s) to add. 2. In the **Usage** table, find the product you want to rate and click **...** > **Add Tiers**. 3. Define the tiers and dollar amounts. Fill out the minimum usage value on the left (exclusive) and the maximum usage value on the right (inclusive). 4. Click **Save**. To set tiered pricing with the API, make a POST request to the [/contract-pricing/rate-cards/addRate](/api-reference/rate-cards/add-a-rate) endpoint and use `"rate_type": "tiered"`. # Create products Source: https://docs.metronome.com/guides/implement-metronome/core-concepts/create-products-contracts Products in Metronome represent your company’s individual product or service offerings. This is analogous to SKUs or items in an ERP system. For example, an infrastructure company’s products might include Reads, Writes, and Storage. For an AI company, the products might map to individual models. a diagram showing where products fit into the metronome data model Products defined in Metronome dictate: * **How a customer gets charged** Products can either be usage-based, composite (derived from usage-based or other composite products), subscription-based, or fixed (for example, a platform fee). * **Invoice line item display** Each product (or grouping of products) becomes a line item on generated invoices. **PRODUCTS DON'T HAVE PRICES** Products determine *how* a customer is charged (for example, which billable metrics impact a charge), but they don't dictate *how much* a customer pays. For usage-based, composite, and subscription products, prices are set on a [rate card](/guides/get-started/core-concepts/create-manage-rate-cards), which you can modify on a [contract](/guides/get-started/core-concepts/provision-contract). Prices on fixed products are set on a contract. ## Product types​ Metronome supports four types of products: * **Usage** , variably priced based on reported customer usage for the period. With usage products, you must [set up billable metrics beforehand](/guides/get-started/core-concepts/create-billable-metrics/). Associate each product to a single billable metric. The same billable metric can be associated with multiple products. * **Composite** , percentage charge on a group of applicable products. You can define the applicable products by id or product tag, and can choose whether nested composite charges are included. * **Subscription** , a recurring fee billed on a schedule. Use subscription fees for seat billing models, platform fees, or other recurring charges. * **Fixed** , used to power scheduled charges, commits, and credits. ## Create products​ To define products in the [Metronome app](https://app.metronome.com/products), go to Offering -> Products -> click **+ Add new product** : ### Usage-based products 1. Give the product a meaningful name; this will appear on customer invoices. 2. (Optional) Enter any product tags. Product tags simplify new product launches and bulk discounting. 3. Select the product type: usage. 4. Select a billable metric. 5. (Optional) Add presentation and pricing group keys. Presentation and pricing group keys can only be added if they have been defined as group keys on the underlying billable metric. This field is only applicable for usage products. 6. (Optional) Add a quantity conversion. Multiply or divide by a conversion factor. This field is only applicable for usage products. 7. (Optional) Add rounding. Round up, down, or half up to the specified number of decimal places. This field is only applicable for usage products. 8. Click **Save**. ### Composite products 1. Give the product a meaningful name; this will appear on customer invoices. 2. (Optional) Enter any product tags. Product tags simplify new product launches and bulk discounting. 3. Select the product type: composite. 4. Choose to include nested composite spend. If enabled, composite products will appear in the product selection list. 5. Select applicable products or applicable product tags. 6. Click **Save**. ## Update products​ Within Metronome, you can edit products even when they're actively in use for customer billing. Changes to products are scheduled to take effect at a specified `Starting at` time, which you can define when changing a product. This date can be set in the future to schedule out product changes ahead of time. If set in the past, it will be retroactively applied at the time specified. The following fields are available to edit for usage-based products: * Name * Tags * Billable metric * Quantity conversion * Rounding * Pricing and presentation group keys (only editable with the API) You cannot change the product type. If you create a product with the wrong type, create a new product with the correct type and archive the original product. To update products in the [Metronome app](https://app.metronome.com/products), go to Offering -> Products: 1. Click on the product to edit. 2. In the product details pane, click the overflow action -> **Edit product...** 3. In the resulting modal, set the **Starting at** value to specify when the product edits should take effect and update the desired product fields. 4. Click **Save**. ## Product tags​ Metronome supports adding one or more tags to products. Consistent use of tags helps you select products more easily, whether when creating a composite product or adding products to a commit or discount. Product tags are also useful for adding your company's internal identifying information to your products in Metronome. For example, you may have internal product codes that you want to store in Metronome to maintain a consistent integration pattern across your systems. ## Group keys​ You can set two types of group keys on your new product: pricing group key and presentation group keys. To set a group key on a product, you must use a billable metric with the relevant group keys. You can use these group keys to encode your price book and customize the display of invoices in Metronome. ### Pricing group keys​ Many AI and infrastructure companies opt to price their products differently across dimensions like region and cloud provider. This approach aligns COGS and revenue, allowing for consistent margins across SKUs within a product catalog. Pricing group keys allow you to set different prices for the same product based upon a set of variables you can choose during product creation. For example, you have two products (P1 and P2), priced per hour of uptime. To support this pricing model, set the `region` and `cloud_provider` fields as pricing group keys on the products. The unique rates for each key-value permutation are then defined on the Metronome rate card: | | Region 1, AWS | Region 1, AZURE | Region 2, AWS | Region 2, AZURE | | --------- | ------------- | --------------- | ------------- | --------------- | | Product 1 | \$0.12/hr | \$0.14/hr | \$0.16/hr | \$0.18/hr | | Product 2 | \$0.18/hr | \$0.22/hr | \$0.20/hr | \$0.24/hr | In the above setup, you only need to create and manage two products while encoding eight distinct rates. Metronome doesn’t restrict the number of pricing group keys you can use when defining pricing. To learn more about configuring rates in Metronome, see [Manage rate cards](/guides/get-started/core-concepts/create-manage-rate-cards). ### Presentation group keys​ You may want to override the display of information on an invoice by grouping across certain properties. Do this with presentation group keys, which will group a set of line items together. Pricing and presentation group keys can be the same property if desired. For example, you have two products, two regions, and two orgs. The pricing group key in this situation is `region`, while the presentation group key will be `org`. This allows you to split out `region` level usage by `org`. The resulting invoice contains: | | Region 1, Product 1 | Region 2, Product 1 | Region 1, Product 2 | Region 2, Product 2 | | ----- | ------------------- | ------------------- | ------------------- | ------------------- | | Org 1 | 15 units | 10 units | 10 units | 5 units | | Org 2 | 10 units | 0 units | 6 units | 3 units | Showing your customers usage at a granular level enables them to derive novel insights from their usage patterns. **CONFIGURATION NOTE** Using multiple pricing and presentation group keys with many possible values for a given customer can increase latency when calling the Metronome API. If you anticipate the cardinality of these possible values reaching one thousand, contact us via the [Metronome support portal](https://support.metronome.com/) to discuss your configuration. # How Metronome invoices work Source: https://docs.metronome.com/guides/implement-metronome/core-concepts/how-invoicing-works Invoices in Metronome represent the products or services sold to or consumed by your customers. This page describes invoice types, statuses, line items, and configurable presentation. **CUSTOMER BILLING** To learn how to bill your customers and collect payment for Metronome invoices, view our [invoicing guides](/guides/invoices/overview) In the context of usage-based billing, where customers are charged based on actual consumption of a service (like cloud storage, API calls, or data processing), the invoice plays a crucial role for several reasons: * **Transparency** In a usage-based model, the amount charged can vary month to month. The invoice itemizes what was used, when it was used, and how charges were calculated, providing clarity to the customer about what they're paying for. * **Accuracy** Accurate invoices ensure that the customer is billed only for the resources they actually consumed. This minimizes disputes and ensures trust between the service provider and the customer. * **Revenue recognition** For businesses, invoices are necessary for tracking revenue and ensuring that the right amounts are recorded based on actual usage. * **Compliance** In many industries, regulatory requirements mandate accurate invoicing for tax and legal purposes. Invoices help companies comply with tax laws, as they document when services were provided and when payments are due. * **Cash flow management** Invoices also signal to customers when payments are due, helping businesses manage their cash flow. In usage-based billing, timely invoicing helps businesses maintain steady revenue from varying usage patterns. The primary mechanism generating invoices in Metronome is the contract. When you provision a contract for a customer, it automatically produces invoices throughout its lifecycle on predefined schedules. ## Types of Metronome invoices​ Metronome produces two types of invoices: usage invoices and scheduled invoices. ### Usage invoices​ Usage invoices record the products or services a customer is entitled to and what they've consumed in a given period. These are generated according to the usage statement schedule and frequency defined in the contract. They're continuously updated in real time, providing visibility into customer spend. If a customer has a credit or prepaid commitment applied, the usage invoice may reflect a zero-dollar total and not require payment. In these cases, the usage invoice serves as a record for revenue recognition and can be displayed through a dashboard instead of getting sent for payment collection. A usage invoice includes: * All services the customer is entitled to, as listed on the rate card with the list price, customer-specific price, and the quantity consumed * All commitments and credits applied to the invoice **Unique features** Schedule changes to any product, rate, commitment, or credit in Metronome. These changes are automatically reflected on the invoice without requiring the issuance of a new invoice. Additionally, Metronome breaks down the usage invoice into distinct time periods, detailing when various services were entitled, rates were active, and commitments or credits were available. Metronome applies the commitments or credits to each line item and calculates the overage per item. This flexibility helps you schedule mid-period changes to a billable metric or price and have the invoice automatically adjust. **Schema** Usage invoices are identified by the type `USAGE` and are always associated with a billing period, defined by the `billing_period_start_date` and `billing_period_end_date`. Usage invoices have a configurable grace period, during which usage can still be reported after the `billing_period_end_date`. Once finalized, the invoice is issued on the `issue_date`. ### Scheduled invoices​ Metronome contracts can also produce scheduled invoices. These are used for fixed charges like commitment prepayments, postpaid commitment true-ups, or simple upfront or recurring fees. Generate a scheduled invoice by adding a commitment or scheduled charge to a contract. **Unique features** Metronome offers a highly flexible set of scheduling options. Create a custom billing schedule that meets your customer needs, enabling you to close deals faster. Schedule charges to invoice monthly, quarterly, or even define precise custom schedules. Metronome automatically groups all scheduled charges onto the same invoice. **Schema** Scheduled invoices are identified by the type `SCHEDULED`. There is no grace period for these invoices. They are finalized on the configured `issue_date` (see limitations below) and do not have a `billing_period_start_date` or `billing_period_end_date`. **SCHEDULED INVOICE FINALIZATION MECHANICS** Scheduled invoices are finalized according to specific timing rules based on their issue date and contract creation time: * If the issue date is in the past or present, the invoice is finalized immediately * If the issue date is within 2 hours of contract creation, the invoice is finalized within 2 hours and 30 minutes of the contract being created * If the issue date is more than 2 hours from contract creation, the invoice is finalized within 30 minutes of the issue date ## Invoice lifecycle​ All invoices are in one of four states: draft, grace period, finalized, or void. ### Draft invoices​ Draft is an initial invoice state. What occurs during or after that state depends upon the invoice type. **Usage invoices** As soon as a contract billing period starts, Metronome creates a draft usage invoice (`status` = `DRAFT`). As usage data is sent to Metronome, the draft invoice continuously updates to reflect real-time spend. **Scheduled invoices** Once you add scheduled charges or prepaid commitments to a contract, Metronome creates draft scheduled invoices (`status` = `DRAFT`). These remain in draft until the scheduled invoice date. For postpaid commitments, Metronome automatically creates a draft true-up invoice (`status` = `DRAFT`). This invoice tracks how much more the customer needs to spend to meet their commitment. It finalizes after the last usage invoice for that contract finalizes. ### Grace period​ After the billing period ends, Metronome enforces a grace period before finalizing the invoice. This buffer period allows for late-arriving usage data and invoice corrections. The grace period is 24 hours by default. Contact us via the [Metronome support portal](https://support.metronome.com/) to customize the grace period. ### Finalized invoices​ Once an invoice is finalized (`status` = `FINALIZED`), no further changes can be made, even if additional usage is reported for the period. The finalized invoice is immutable and ready for customer delivery and official reporting. If the finalized invoice contains errors, it can be voided and regenerated, incorporating any updated changes. Finalized invoices are distributed and collected based on your contract's [billing configuration](/guides/customers-billing/manage-customers/provision-a-customer#add-a-billing-configuration-to-a-customer). ### Voided invoices A finalized invoice can be voided (`status` = `VOID`) if it was created in error due to a provisioning issue. **REGENERATE VOIDED INVOICES** Once an invoice has been voided, you can regenerate it through the UI when viewing the invoice, or through the [/invoices/regenerate](/api-reference/invoices/regenerate-an-invoice) API endpoint. When an invoice is regenerated, it will be recalculated using up-to-date usage and pricing terms. ## Invoice line items Each invoice consists of line items corresponding to products and services in Metronome. Each line item includes: * **Display name** , the name of the product or service * **Quantity (decimal number)** , a default quantity or one computed from customer usage data * **Unit price** , the price per unit of the service * **Total** , automatically calculated by multiplying the quantity by the unit price * **Pricing and presentation group keys** , optional grouping information to organize pricing data ## Invoice example​ This example shows how Metronome creates invoice line items. Your customer is provisioned with access to a product named API Tokens with a unit price of \$1 per unit. The customer also prepurchased a \$50 prepaid commit, which corresponds to 50 tokens. If the customer used 80 tokens in the current billing period, the Draft invoice is broken down into: All monetary values in this invoice are in the currency's denomination. For USD, values are in **cents** — so a `"total"` of `3000` means \$30.00 and a `"unit_price"` of `100` means \$1.00. Other currencies may use whole units. See [currency denomination](/guides/pricing-packaging/make-pricing-changes/use-currency-custompricingunits#currency-denomination) for details. * A line item for the first 50 tokens consumed resulting in a total of \$50 * A line item adjustment indicating that the \$50 prepaid commitment offset the total for the first \$50 * A line item covering the remaining 30 tokens consumed for a total of \$30 ```json theme={null} { "id": "INVOICE_ID", "issued_at": "2024-10-02T00:00:00+00:00", "start_timestamp": "2024-09-01T00:00:00+00:00", "end_timestamp": "2024-10-01T00:00:00+00:00", "customer_id": "CUSTOMER_ID", "customer_custom_fields": {}, "type": "USAGE", "credit_type": { "id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "name": "USD (cents)" }, "status": "DRAFT", "total": 3000, "external_invoice": null, "contract_id": "CONTRACT_ID", "contract_custom_fields": {}, "custom_fields": {}, "billable_status": "billable", "line_items": [ { "product_id": "PRODUCT_ID", "product_type": "UsageProductListItem", "product_custom_fields": {}, "name": "Tokens Consumed", "total": 5000, "credit_type": { "id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "name": "USD (cents)" }, "starting_at": "2024-09-01T00:00:00+00:00", "ending_before": "2024-10-01T00:00:00+00:00", "commit_id": "COMMIT_ID", "commit_segment_id": "COMMIT_SEGMENT_ID", "commit_type": "PrepaidCommit", "commit_custom_fields": {}, "unit_price": 100, "quantity": 50 }, { "product_id": "PRODUCT_ID", "product_type": "UsageProductListItem", "product_custom_fields": {}, "name": "Prepaid Tokens applied", "total": -5000, "credit_type": { "id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "name": "USD (cents)" }, "starting_at": "2024-09-01T00:00:00+00:00", "ending_before": "2024-10-01T00:00:00+00:00", "commit_id": "COMMIT_ID", "commit_segment_id": "COMMIT_SEGMENT_ID", "commit_type": "PrepaidCommit", "commit_custom_fields": {} }, { "product_id": "PRODUCT_ID", "product_type": "UsageProductListItem", "product_custom_fields": {}, "name": "Tokens Consumed", "total": 3000, "credit_type": { "id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "name": "USD (cents)" }, "starting_at": "2024-09-01T00:00:00+00:00", "ending_before": "2024-10-01T00:00:00+00:00", "unit_price": 100, "quantity": 30 } ] } ``` The [Metronome app](https://app.metronome.com/) visualizes the invoice object, showing the usage quantity continuously updated as usage events are ingested for this customer and adjustments like prepaid commit and credits grants applied. Invoice visualization ## Invoice presentation​ In Metronome, you control how your invoices are structured and the level of granularity to provide your customers to ensure trust and confidence. You can configure: * A clear product name that Metronome shows as the line item description. * The optional pricing group keys to add granularity on each usage product. For example, you can set a different price for input and output tokens. * The optional presentation group keys for grouping usage products under a property like a team name or an organization name. ### Line items with pricing group keys​ You can configure usage products with one or multiple pricing grouping keys and set a rate for each pricing group key combination. Metronome invoices automatically have a separate line item for each combination of pricing group keys. Consider the example of `Tokens Consumed`, where you add a pricing group key `type` to the product and set two rates in the rate card: one for `type = input` and one for `type = output`. The invoice now has two line items, showing the pricing group key value for each: Invoice with pricing grouped keys Note that unlike usage products without a pricing group key, Metronome does not create line items for each pricing group key unless it has usage data. ### Group line items with presentation group keys​ On top of pricing group keys, group usage products on an invoice by any relevant property. This helps your customers do things like allocate spend to the appropriate business unit. Consider the previous example where customers create `projects` and consume tokens by project. You want to group the usage line items by `project_name` on the invoice. To do so, set a presentation group key on your `Tokens Consumed` product. The Metronome invoice automatically groups line items by `project_name`. Invoice with presentation grouped keys # Non-monotonically increasing metrics Source: https://docs.metronome.com/guides/implement-metronome/core-concepts/non-monotonically-increasing-metrics Most billable metrics in Metronome track usage that only goes up over time — for example, the total count of API calls made. These are **monotonically increasing** metrics. However, some metrics can fluctuate up *and* down over a billing period — for example, the number of connected devices or storage in use. These are **non-monotonically increasing** metrics, and they require a few special considerations when working with Metronome contracts, commits, credits, rate changes, and usage APIs. Non-monotonically increasing metrics typically use the `latest` aggregation type, which captures the most recent reported value at each point in time rather than counting or summing all events together. This page covers behavioral nuances specific to non-monotonically increasing (e.g., `latest`) metrics. For general information about creating billable metrics, see [Create billable metrics](/guides/implement-metronome/core-concepts/create-billable-metrics#1-identify-usage-components). ## How Metronome bills non-monotonically increasing metrics When Metronome processes a `latest` metric for billing purposes, it calculates the **incremental change** between consecutive reporting windows rather than billing on the absolute value. This is a critical distinction that affects how charges, commits, credits, and rate changes are applied. **Example:** You send in the following `latest` values over four days: | Day | Reported value | Incremental quantity billed | | ----- | -------------- | --------------------------- | | Day 1 | 7 | 7 | | Day 2 | 9 | 2 *(9 − 7)* | | Day 3 | 10 | 1 *(10 − 9)* | | Day 4 | 5 | −5 *(5 − 10)* | Metronome computes the daily incremental change and uses that as the billable quantity. When the reported value **decreases**, the incremental quantity is **negative**, which results in a credit back to the customer for that period. ## Commit and credit coverage Commits and credits apply only to the **incremental usage that falls within their effective date range** — not the absolute reported value. ### Example Suppose you have a `latest` metric and send the following values: * **Day 1:** reported value = **7** * **Day 2:** reported value = **9** You create a contract with a commit that covers **Day 2 onward only**. Even though the absolute value on Day 2 is 9, the commit only covers the **incremental quantity** of **2** (the change from 7 to 9). The usage from Day 1 (quantity of 7) is not covered by the commit because it falls outside the commit's effective range. | Period | Reported value | Incremental quantity | Covered by commit? | | ------ | -------------- | -------------------- | ------------------ | | Day 1 | 7 | 7 | No | | Day 2 | 9 | 2 | Yes | This behavior ensures that commits and credits are applied proportionally to the usage that actually occurred during their effective period. The same logic applies to **credits**. In the invoice below, the \$100 credit labeled "Free credit" covers only the incremental quantity that falls within its effective date range (March 17th onward). **Example invoice with credit coverage:** | Name | Applied commit or credit | Effective date | Quantity | Unit price | Total | | -------------- | ------------------------ | -------------- | -------- | -------------------- | ------------ | | Latest Product | – | Mar 1 – Mar 17 | 40 | \$3.00 | \$120.00 | | Latest Product | Free credit | Mar 17 – Apr 1 | 25 | \$4.00 | \$100.00 | | Latest Product | – | Mar 17 – Apr 1 | 55 | \$4.00 | \$220.00 | | | | | | Free credit consumed | −\$100.00 | | | | | | **Total due** | **\$340.00** | In this example, the free credit covers 25 of the 80 incremental units that accrued during the Mar 17 – Apr 1 period. The remaining 55 units are billed at the standard rate. ## Rate changes When a rate change takes effect mid-period, Metronome applies each rate only to the **incremental usage that occurred during that rate's effective window**. This interacts with non-monotonically increasing metrics in two important ways depending on whether the value increased or decreased. ### Scenario 1: Value increases (incremental is positive) * **Day 1:** reported value = **7** (rate = \$3.00/unit) * **Day 2:** reported value = **9** (rate changes to \$4.00/unit) The incremental quantity on Day 2 is **2**. Only that quantity of 2 is billed at the new \$4.00 rate. Day 1's quantity of 7 remains at \$3.00. | Period | Quantity | Rate | Charge | | ------ | -------- | --------- | ----------- | | Day 1 | 7 | \$3.00 | \$21.00 | | Day 2 | 2 | \$4.00 | \$8.00 | | | | **Total** | **\$29.00** | ### Scenario 2: Value decreases (incremental is negative) When the reported value drops after a rate change, the **negative incremental quantity** is priced at the **new rate**, resulting in a credit at that rate. * **Mar 1 – Mar 17:** reported value reaches **40** (rate = \$3.00/unit) * **Mar 17 – Apr 1:** reported value drops by **10** (rate changes to \$4.00/unit) **Example invoice with rate change and negative quantity:** | Name | Effective date | Quantity | Unit price | Total | | -------------- | -------------- | -------- | ------------- | ----------- | | Latest Product | Mar 1 – Mar 17 | 40 | \$3.00 | \$120.00 | | Latest Product | Mar 17 – Apr 1 | −10 | \$4.00 | −\$40.00 | | | | | **Total due** | **\$80.00** | In this case, the customer is billed \$120.00 for the first period at \$3.00/unit, then credited \$40.00 for the decrease of 10 units at the new \$4.00 rate, resulting in a net total of **\$80.00**. Because negative incremental quantities are priced at the **current effective rate** (not the original rate), a rate increase combined with a usage decrease can result in a credit that is larger per unit than the original charge. Make sure your rate change timing accounts for this behavior. ## Credits combined with rate changes and usage decreases When a credit is present alongside a rate change and a usage decrease, the interaction between these factors can produce **negative invoice totals**. This happens because Metronome evaluates each charge line independently and applies credits as it encounters positive charges — it does **not** look ahead to account for negative charges that appear later on the invoice. ### Example Using the same scenario as above — a rate change from \$3.00 to \$4.00 on Mar 17, with usage rising to 40 then dropping by 10 — now add a **\$100.00 free credit** that covers the full billing period. Metronome processes the charges in chronological order: 1. **Mar 1 – Mar 17:** 40 units × \$3.00 = \$120.00. The \$100.00 credit is applied here, covering 33.33 units. The remaining 6.67 units are billed at \$3.00. 2. **Mar 17 – Apr 1:** −10 units × \$4.00 = −\$40.00. This negative charge is processed as-is — the credit has already been consumed. **Example invoice with credit, rate change, and negative quantity:** | Name | Applied commit or credit | Effective date | Quantity | Unit price | Total | | -------------- | ------------------------ | -------------- | -------- | -------------------- | ------------ | | Latest Product | Free credit | Mar 1 – Mar 17 | 33.33 | \$3.00 | \$100.00 | | Latest Product | – | Mar 1 – Mar 17 | 6.67 | \$3.00 | \$20.00 | | Latest Product | – | Mar 17 – Apr 1 | −10 | \$4.00 | −\$40.00 | | | | | | Subtotal | \$80.00 | | | | | | Free credit consumed | −\$100.00 | | | | | | **Total due** | **−\$20.00** | The subtotal of the charges is \$80.00 (the same as the scenario without a credit). However, the full \$100.00 credit was consumed against the first tranche of positive charges. The result is a **negative total due of −\$20.00**. **Metronome does not look forward when applying credits.** Credits are drawn down against positive charge line items as they are encountered. The system does not pre-calculate the net invoice total and limit the credit accordingly. This means that when positive charges early in a period are followed by negative charges later (due to a usage decrease), a credit can be consumed in full even though the net invoice total would have been lower than the credit amount. This can result in negative invoice totals. Keep this in mind when configuring credits for products that use non-monotonically increasing metrics, especially in combination with mid-period rate changes. When using non-monotonically increasing metrics, we recommend configuring commits and credits to cover the **entire billing period** rather than a partial date range. This ensures that credits are applied holistically across all line items, including any negative incremental charges from usage decreases, and avoids unexpected negative invoice totals caused by credits being fully consumed against early positive charges before later negative charges are processed. ## Invoice breakdowns When you call the [invoice breakdowns endpoint](/api-reference/invoices/list-invoice-breakdowns), Metronome returns the **incremental quantity and its associated cost for each time window** — not the absolute reported value. This includes negative quantities when usage decreases. ### Example You send the following `latest` values: | Day | Reported value | | ----- | -------------- | | Day 1 | 7 | | Day 2 | 9 | | Day 3 | 10 | | Day 4 | 5 | The invoice breakdowns endpoint returns: | Day | Quantity | Cost | | ----- | -------- | --------------- | | Day 1 | 7 | 7 × unit price | | Day 2 | 2 | 2 × unit price | | Day 3 | 1 | 1 × unit price | | Day 4 | −5 | −5 × unit price | The **quantity** column reflects the incremental change, and the **cost** is calculated based on that incremental quantity. Negative quantities produce negative costs (credits). This breakdown gives you a granular, day-by-day view of how the metric's value changed and how each change was priced. ## Usage endpoints Unlike invoice breakdowns, the [usage endpoints](/api-reference/usage/get-usage-data-with-paginated-groupings) return the **absolute latest reported value per time window** — not the incremental change. The value you see depends on the granularity you request. ### Example You send the following `latest` values: | Day | Reported value | | ----- | -------------- | | Day 1 | 7 | | Day 2 | 8 | | Day 3 | 9 | **With a daily breakdown**, the usage endpoint returns: | Day | Value | | ----- | ----- | | Day 1 | 7 | | Day 2 | 8 | | Day 3 | 9 | **With no breakdown** (full period), the usage endpoint returns: | Period | Value | | ------------- | ----- | | Day 1 – Day 3 | 9 | The value returned with no breakdown is the **latest reported value** across the entire queried window. **Key distinction:** Invoice breakdowns show **incremental quantities** (the change between windows), while usage endpoints show the **absolute latest value** within each window. Keep this difference in mind when reconciling data between the two. ## Summary | Behavior | What to expect | | ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | | Billing quantity | Incremental change between reporting windows — can be negative | | Commits and credits | Applied only to incremental usage within the commit/credit's effective date range | | Rate changes | Each rate applies to the incremental quantity during its effective window; negative increments are priced at the current rate | | Credits + rate changes + decreases | Credits are consumed against positive charges as encountered; they do not look ahead. This can result in negative invoice totals. | | Invoice breakdowns | Returns incremental quantities and costs per time window, including negative values | | Usage endpoints | Returns the absolute latest value per time window (not incremental) | # Create packages Source: https://docs.metronome.com/guides/implement-metronome/core-concepts/packages-overview A package is a reusable, time-relative set of contract terms. Packages enable you to maintain only one rate card while supporting a variety of pricing plans to optimize for simplicity and flexibility. Define a package in Metronome to encode a standardized set of contract terms once and then provision many customers against that same package, making it easy to manage cohorts with identical contract structures. Use packages to model standard pay-as-you-go motions with Good/Better/Best plans (see the [Pay as you go guide](https://docs.metronome.com/guides/pricing-packaging/billing-model-guides/pay-as-you-go)) to provision customers in a consistent and scalable way. ## Prerequisites Before creating a package, you must have: * Your [**usage events**](https://docs.metronome.com/guides/events/design-usage-events) connected to Metronome * A [**billable metric**](https://docs.metronome.com/guides/get-started/core-concepts/create-billable-metrics) * A [**product**](https://docs.metronome.com/guides/get-started/core-concepts/create-products-contracts) * A [**rate card**](https://docs.metronome.com/guides/get-started/core-concepts/create-manage-rate-cards) ## Create a package Create packages using the `/packages/create` endpoint. Package creation is nearly identical to [contract creation](https://docs.metronome.com/guides/get-started/core-concepts/provision-contract), with the following exceptions: * **Packages are customer agnostic.** Do not pass a `customer_id` or a customer billing configuration when creating a package * **Packages are time-relative.** Set `starting_at_offset` and `duration` for relative lengths instead of `starting_at` and `ending_before` dates. * **Packages support aliases.** Similar to rate card aliases, packages support aliases that aid in programmatically managing new package rollouts. Consider an example AI company, Gnome AI, with a Starter Plan that includes: * a \$10 recurring sign-up credit applied to input and output tokens for the first 3 months * a \$10 monthly subscription fee * Standard input and output token rates To create this package in the Metronome app, go to Offering → Packages → Add package. 1. Give the package an internally meaningful **Name** (for example, *Starter Plan - October 2025*) 2. Add an optional **Description** (for example, *Standard Starter Plan pricing as of October 1, 2025*) 3. Optionally **Add aliases.** Aliases can be used in place of Metronome-generated package ID when provisioning contracts via API. [Read more](https://docs.metronome.com/guides/pricing-packaging/make-pricing-changes/make-a-pricing-change) about how aliases help you launch new pricing while maintaining your integration infrastructure. 4. **Set billing terms.** Set the default duration of the contract, net payment terms, and billing provider. 5. **Choose a rate card.** This will determine the rates used for each package. 6. **Add terms**. Add commits, credits, subscriptions, threshold billing, or scheduled charges to the package. All contracts provisioned with a package will contain the defined terms. For the above Starter Plan, add a recurring sign-up credit and monthly subscription fee. 7. **Add overrides.** Add overrides to any rate associated with the selected rate card. You can set overrides with relative or absolute dates. All contracts provisioned with a package will contain the defined overrides. 8. Review the rate card and click **Save** to create the completed card. To create this package using the API, execute the following call: ```json theme={null} curl https://api.metronome.com/v1/packages/create \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "name": "Starter Plan (as of Oct 2025)", "rate_card_alias": "Tokens rate card", "aliases": [{ "name": "Starter Plan", "starting_at": "2025-10-01T00:00:00.000Z" }], "net_payment_terms_days": 15, "duration": { "value": 12, "unit": "MONTHS" }, "recurring_credits": [{ "product_id": "5cd945a1-7a70-4875-b2b3-f9e3b28c647c", "access_amount": { "unit_price": 1000, "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2" }, "priority": 1, "commit_duration": { "value": 1, "unit": "PERIODS" }, "starting_at_offset": { "value": 0, "unit": "MONTHS" }, "duration": { "value": 3, "unit": "MONTHS" } }], "subscriptions":[{ "collection_schedule": "advance", "initial_quantity": 1, "proration": { "invoice_behavior": "BILL_IMMEDIATELY", "is_prorated": true }, "subscription_rate": { "billing_frequency": "monthly", "product_id": "76f29162-7f5c-4ee6-89ed-ebbd592d767e" }, }] }' ``` **INFO** Use `starting_at_offset` on package terms to define `starting_at` relative to contract start date and `duration` to define `ending_before` relative to the `starting_at_offset`. For terms with point-in-time dates without a duration, use `date_offset` ## Provision customers with a package Provision a customer using the `/contracts/create` endpoint. To provision a customer with the example Starter Plan package, execute the following API call: ```json theme={null} curl https://api.metronome.com/v1/contracts/create \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "aa58107d-162f-407e-9f09-940f16adbb1c", "starting_at": "2025-10-01T00:00:00.000Z", "package_alias": "Starter Plan" }' ``` The customer is now provisioned with a Starter Plan contract beginning October 1, 2025, with a \$10 monthly subscription for the contract duration and a \$10 recurring credit that ends on Jan 1, 2026. Contracts provisioned with a package have an attached package ID that is viewable in the Metronome app, data export, and API. **STANDARD PACKAGES ONLY** Metronome currently only accepts `package_id` (or `package_alias`) and `transition` when provisioning a customer with a package. Passing in any additional terms to the createContract call will return a 400 error when used in conjunction with packages. ## Update package pricing Packages currently cannot be edited after creation. To introduce a new package version, create a new package and set the alias schedule. For example, Gnome AI decides to update their Starter Plan packaging so that new customers no longer receive the /\$10 sign-up credit as of Feb 1, 2026. To model this scenario in Metronome, create a new package with the same *Starter Plan* alias: ```json theme={null} curl https://api.metronome.com/v1/packages/create \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "name": "Starter Plan - Feb 2025", "rate_card_alias": "Tokens rate card", "aliases": [{ "name": "Starter Plan", "starting_at": "2026-02-01T00:00:00.000Z" }], "net_payment_terms_days": 15, "duration": { "value": 12, "unit": "MONTHS" }, "subscriptions":[{ "collection_schedule": "advance", "initial_quantity": 1, "proration": { "invoice_behavior": "BILL_IMMEDIATELY", "is_prorated": true }, "subscription_rate": { "billing_frequency": "monthly", "product_id": "76f29162-7f5c-4ee6-89ed-ebbd592d767e" } }] }' ``` Since Gnome AI is already provisioning customers using the *Starter Plan* alias, all new clients signing up after February 1, 2026 at midnight UTC will automatically be provisioned on the new package without needing to make any changes to existing logic. ## View and manage packages To view existing packages, go to Offering → Packages in the Metronome app or call `/packages/list` in the API. For easier cohort management, view customers associated with a given package in the Metronome app or call `/packages/listContractsonPackage` in the API. **PACKAGES CANNOT BE EDITED** Create a new package and provision a customer with the new package or edit the underlying contract using editContract. ## Set custom fields on package terms When creating a package, users can set [custom fields](https://docs.metronome.com/api-reference/custom-fields#custom-fields) on package terms. Custom fields on package terms will be passed down to associated contracts. Package custom fields cannot be updated after set, but custom fields set by packages at the contract-level can be updated using `/customFields/setValues`. Currently, Metronome supports custom fields for: `package_commit`, `package_credit`, `package_scheduled_charge`, and `package_subscription`. # Provision a customer contract Source: https://docs.metronome.com/guides/implement-metronome/core-concepts/provision-contract Define a contract in Metronome that encodes the products customers can access, rates for each product, and access duration. Just as rate cards are built on products, contracts are built on rate cards. A contract references a specific rate card and bundles it with other Metronome models like [commits,](/guides/pricing-packaging/apply-credits-and-commits/create-a-pre-paid-commit) discounts, fixed products that don’t live on the rate card, and more. Create contracts with the Metronome app or with the [/contracts/create](/api-reference/contracts/create-a-contract) endpoint. ## Prerequisites Before provisioning a contract you must have: * Your [usage events](/guides/events/design-usage-events) connected to Metronome * A [billable metric](/guides/get-started/core-concepts/create-billable-metrics/) * A [product](/guides/get-started/core-concepts/create-products-contracts) * A [rate card](/guides/get-started/core-concepts/create-manage-rate-cards) * A [customer](/guides/get-started/core-concepts/provision-customer) * A [`customer_billing_provider_configuration`](/guides/get-started/core-concepts/provision-customer) ### Create a contract​ Consider an example where your customer, WidgetsExpress, purchased a prepaid commit for \$10,000 that applies to your cloud products via AWS Marketplace. This commit lasts for a year. As part of the contract, they also pay a \$1,000 platform fee each quarter to use your service. They pay for the prepaid commit once upfront and for usage on a monthly basis. To provision this contract with the [Metronome app](https://app.metronome.com/): 1. Navigate to *Customers* and select your newly created customer. 2. On the *Overview* tab, click the **+ Add** button on the right hand side of the *Contracts* pane. 3. Fill in the *Basic info* for the contract like the contract name, start date, and rate card to use. Be sure to set the billing provider to AWS. 4. Under *Terms* , click **Add - > Commit** and fill in the details for the prepaid commit. 5. Under *Terms* , click **Add - > Scheduled charges** and add the platform fee as a scheduled charge. The final contract looks like: Final contract To create the example contract with the `/contracts/create` API, execute this call: ```bash theme={null} curl https://api.metronome.com/v1/contracts/create \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "aa58107d-162f-407e-9f09-940f16adbb1c", "rate_card_alias": "base_usage_products", "starting_at": "2024-11-01T00:00:00.000Z", "billing_provider_configuration": { "billing_provider": "aws_marketplace", "delivery_method": "direct_to_billing_provider" }, "commits": [ { "type": "prepaid", "name": "Contract Prepaid Commit", "product_id": "a1f4e40b-f8c4-496b-b687-0a103396b479", "access_schedule": { "schedule_items": [ { "amount": 1000000, "starting_at": "2024-11-01T00:00:00.000Z", "ending_before": "2025-11-01T00:00:00.000Z" } ] }, "invoice_schedule": { "schedule_items": [ { "unit_price": 1000000, "quantity": 1, "timestamp": "2024-11-01T00:00:00.000Z" } ] }, "applicable_product_tags": ["cloud"], "description": "Usage Commit" } ], "scheduled_charges": [ { "product_id": "06cf3703-3f5e-467c-8ba1-0ee934c740b9", "name": "Platform Charge", "schedule": { "recurring_schedule": { "starting_at": "2024-11-01T00:00:00.000Z", "ending_before": "2025-11-01T00:00:00.000Z", "frequency": "quarterly", "unit_price": 100000, "quantity": 1, "amount_distribution": "each" } } } ], "usage_statement_schedule": { "frequency": "monthly", "day": "contract_start" } }' ``` **BETA** You can add a `billing_provider_configuration` to a contract that was created without one - potentially as part of a free trial conversion - via contract editing. The billing configuration will take effect at the start of the current billing period. For Stripe, this means that the current invoice will be sent to Stripe at the end of the month. For marketplaces, this means the entire billing period will be metered to the marketplace. For free trial use cases, ensure the customer is credited for the free trial so the free usage is not billed. ## Consolidate usage and scheduled invoices​ You have the option to specify if scheduled invoices should consolidate onto a customer's usage invoices. This setting applies to all charges (including commits) on the contract. It follows this logic to determine whether to consolidate invoices: * The last day of the usage service period (exclusive) falls on the same day as the scheduled date for the scheduled invoice. * The corresponding usage invoice hasn’t finalized. Consolidation occurs at the time of contract creation and upon any contract changes in the future. Consider an example where a new customer buys the Best package on your website, which costs \$75 per month. As part of this package, they receive a \$100 monthly commit. The contract and recurring commit start on January 1 with no end date. If `scheduled_charges_on_usage_invoices` is set to `ALL`, the contract creates these invoices: * **Invoice 1:** Issued and finalized on January 1 with one line item for the \$75 monthly charge. * **Invoice 2:** Created in draft with one line item for the \$75 monthly charge in February in addition to all usage charges for January. * **Invoice X:** Assuming no changes to the contract, all future invoices will model invoice 2. ## Add contract discounts and overrides​ Provide discounts during contract creation or by editing an existing contract. Apply discounts with credits, [overrides for product rates](/guides/pricing-packaging/make-pricing-changes/edit-or-override-a-contract), price tiers, and more. If you use dimensional pricing, set price overrides for each combination of group key and product. To add additional terms like credits, commits, overrides for product rates, and more, edit the contract. Consider the example with your mock customer WidgetsExpress to see this in practice. The customer negotiated a discount on cloud products. To address this, edit the contract by overriding products with the `cloud` tag to be 5% off of the basic rate card. To edit a contract with the Metronome app, go to the WidgetsExpress customer → Contracts -> and select the contract that you would like to edit. To edit a contract through the API, execute this call: ```bash theme={null} curl https://api.metronome.com/v2/contracts/edit \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "aa58107d-162f-407e-9f09-940f16adbb1c", "contract_id": "0a6180da-336a-40e6-98f4-20b6be08211d", "add_overrides": [ { "starting_at": "2024-11-01T00:00:00.000Z", "entitled": true, "type": "multiplier", "multiplier": 0.95, "applicable_product_tags": ["cloud"] } ] }' ``` ## Create a usage filter​ You can provision a customer with multiple contracts simultaneously. These contracts can use distinct rate cards, have different start and end dates, discounts, and more. They can all draw down from shared customer-level commits and credits. To specify that usage should count against one contract instead of another, create a usage filter for that contract. For example, your mock customer WidgetsExpress has three sub-divisions: US, EU, and APAC. Each division negotiated different discounts. To model this in Metronome, create a contract for each sub-division and use usage filters to ensure only the appropriate usage gets routed to each contract. When creating the US contract, ensure that only events with the property `region` and value `US` are included in this contract using this API call: ```bash theme={null} curl https://api.metronome.com/v1/contracts/create \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "13117714-3f05-48e5-a6e9-a66093f13b4d", "rate_card_id": "d7abd0cd-4ae9-4db7-8676-e986a4ebd8dc", "starting_at": "2024-10-01T00:00:00.000Z", "usage_filter": { "group_key": "region", "group_values": [ "US" ] } }' ``` You can update the usage filter on a contract at any time, on a schedule. For example, imagine that as of 2025, WidgetsExpress no longer wants usage within their EU division invoiced separately. Instead, they should get billed through the US contract, using US prices. This API call shows how to update the usage filter, with the edit taking effect on Jan 01, 2025: ```bash theme={null} curl https://api.metronome.com/v1/contracts/setUsageFilter \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "13117714-3f05-48e5-a6e9-a66093f13b4d", "contract_id": "d7abd0cd-4ae9-4db7-8676-e986a4ebd8dc", "group_key": "region", "group_values": ["US", "EU"], "starting_at": "2025-01-01T00:00:00.000Z" }' ``` Usage filters have these limitations: * For [streaming billable metrics](/guides/get-started/core-concepts/billable-metrics-basic-filters/), you must define the usage filter as a group key on the underlying billable metric. If you’re also using dimensional pricing and presentation group keys, the usage filter group key must be defined in a compound group key on the underlying billable metric with the dimensional pricing and presentation group keys. * For [SQL billable metrics](/guides/get-started/core-concepts/billable-metrics-sql-editor/), the group key for the usage filter must be present as property value in the underlying events (for example, `properties.region`). ## Add custom fields​ Use [custom fields](/api-reference/custom-fields) to add additional metadata to the contract or commit. This metadata can power downstream processes like revenue recognition workflows. For example, if you’re integrating with SFDC, you can create a custom field for `salesforce_opportunity_id` to map Metronome contracts, and revenue derived from it, to the associated SFDC opportunity. # Provision a customer Source: https://docs.metronome.com/guides/implement-metronome/core-concepts/provision-customer In Metronome, customers are the recipients of an invoice and may represent individual users, enterprises, API keys, or whatever specification your organization needs. This guide describes how to create a customer in Metronome. Creating your customer includes creating the customer object and configuring the optional associated billing configurations. **INFO** A customer needs at least one [contract](/guides/get-started/core-concepts/provision-contract) provisioned to start rating for billing. You can also configure multiple contracts per customer, if needed. ## Create a customer​ Create an individual customer object in Metronome or build a flow to create customers programmatically from system triggers. ### Understand ingest aliases​ Ingest aliases map your internal customer identifiers to Metronome’s customer ID. When you send usage keyed on an ingest alias, Metronome automatically associates it to the correct Metronome customer. This allows you to maintain your existing customer entities without needing to swap in a Metronome customer ID. Ingest aliases can also be used to maintain account hierarchy. Enterprise customers often have sub-organizations that roll up to a single contract. Use ingest aliases to model this. For example, you can represent the enterprise organization as a customer in Metronome, with each sub-organization represented by an ingest alias attached to that customer: ```js theme={null} Parent Account - Metronome Customer e7f893e5-07f7-483b-8c16-6905944c6a89 + Sub-Org 1 - IngestAlias1 + Sub-Org 2 - IngestAlias2 + Sub-Org 3 - IngestAlias3 + Sub-Org 4 - IngestAlias4 ``` You can split out each sub-organization’s usage on the invoice Metronome generates. Learn how to use [group keys](/guides/get-started/core-concepts/create-billable-metrics#3-define-group-keys%E2%80%8B) to modify invoice presentation. Ingest aliases can be specified on the Metronome customer object at time of creation or any point after. Retroactively adding an ingest alias on the customer is a way to take Metronome out of the hot path of customer signup while properly metering usage. For example, if you first send usage keyed on `IngestAlias1` and later add this ingest alias to an existing customer, Metronome retroactively associates that usage to the correct customer. ### Create a customer with the Metronome app​ To create a customer using the app: 1. Go to the **Customers** page → **Add a customer.** 2. Add a name. 3. Add an ingest alias. 4. (Optional) Set a custom field for the customer on the **Settings** tab. ### Build a customer creation flow with the API​ Use the Metronome API to build a flow for creating customers in Metronome programmatically based on sales-led or product-led motions. For a sales-led motion, you might use Salesforce CPQ to capture opportunities. When an opportunity closes, you can schedule a job to create a customer using the Metronome API. This example request shows how to: * Create a mock customer, WidgetsExpress, in Metronome * Codify the relationship between the Metronome customer and the SFDC account by storing the `sfdc_account_id` in a custom field ```bash theme={null} curl https://api.metronome.com/v1/customers \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "ingest_aliases": [ "team@widgetsexpress.com" ], "name": "WidgetsExpress", "custom_fields": { "sfdc_account_id": "sfdc1001" } }' ``` For a product-led growth motion, create a similar workflow where the trigger originates from a signup on your website. Store the relationship between the Metronome customer and your internal customer object. ### Add a billing configuration to a customer A customer in Metronome can be billed in different destinations, often depending on your billing motion. You must first create a `customer_billing_provider_configuration` on the customer and then assign it to a contract. Metronome allows you to configure multiple `customer_billing_provider_configurations` per customer, which means one customer can be billed in multiple systems - one per contract. **INFO** Before setting up a `customer_billing_provider_configuration`, Metronome must first be connected to the relevant system. Follow the steps in [Invoice with Stripe](/integrations/invoice-integrations/stripe) or [Invoice with the Marketplaces (AWS and Azure)](/integrations/marketplace-integrations/aws). Metronome recommends setting the `customer_billing_provider_configurations` on customer creation. For example, let's say WidgetsExpress purchased your product via AWS Marketplace. Amend the previous call to add a `customer_billing_provider_configurations` to the WidgetExpress customer: ```bash theme={null} curl https://api.metronome.com/v1/customers \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "ingest_aliases": [ "team@widgetsexpress.com" ], "name": "WidgetsExpress", "custom_fields": { "sfdc_account_id": "sfdc1001" }, "customer_billing_provider_configurations": [ { "billing_provider": "aws_marketplace", "configuration": { "aws_customer_id": "ABC123ABC12", "aws_product_code": "my_product", "aws_region": "us-west-1" }, "delivery_method": "direct_to_billing_provider" } ] }' ``` After submission, the customer will be created with the associated AWS configuration. However, it will not be billed to AWS until a contract is created with AWS set as the contract's `billing_provider_configuration`. If you do not set a `customer_billing_provider_configuration` on customer creation, you can add one later using the `/setCustomerBillingProviderConfigurations` endpoint. **BETA** You can archive a `customer_billing_provider_configuration` by either archiving the customer or archiving the specific configuration via the `/archiveCustomerBillingProviderConfigurations` endpoint. When you archive a billing configuration, it becomes available for reuse on a new customer. If you archive a `customer_billing_provider_configuration` that is attached to an active contract, the config will be archived on the contract immediately and no longer bill to the associated destination. A new `billing_provider_configuration` cannot be provisioned on the contract. # Send usage events Source: https://docs.metronome.com/guides/implement-metronome/core-concepts/send-usage-events After [designing your usage events](/guides/events/design-usage-events), send them to Metronome. This guide describes what data to send and best practices to ensure event accuracy. **INFO** Send usage events to Metronome through the [/ingest](/api-reference/usage/ingest-events) endpoint or by [connecting Metronome to Segment](/integrations/platform-integrations/segment). ## Usage event structure A usage event is a JSON object with the following fields: ```json theme={null} { "transaction_id": "string", // (required) unique identifier for this event "customer_id": "string", // (required) which customer the event applies to "timestamp": "string", // (required) when the event happened "event_type": "string", // (required) the kind of event, such as page_view or sent_email "properties": {}, // (optional) key/value pairs with event details } ``` * **transaction\_id** Metronome uses the `transaction_id` to ignore duplicate events. Once a usage event is accepted with a given transaction ID, subsequent events within the next 34 days with the same ID are treated as duplicates and ignored. * **customer\_id** The `customer_id` specifies which of your customers is responsible for any billing associated with the event. There are two ways to identify a Metronome customer in usage events: a customer ID or an *ingest alias*. Ingest aliases are useful when sending events using an identifier from your system, such as an email address or account number. Each customer in Metronome may have multiple ingest aliases, and usage events with a `customer_id` matching any of those aliases can be attributed towards that customer's usage. * **timestamp** The `timestamp` must be an [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) string with a 4-digit year, such as `2025-01-23T01:23:45Z`. When querying usage data or producing an invoice, this field is used to select only events that happened in a certain time range. Timestamps more than 24 hours in the future are rejected by the API. * **event\_type** The `event_type` works along with the `properties` map to describe the details of the event. For example, a content delivery network (CDN) might generate events of the type `http_request` with properties like `domain` and `bytes_sent` to support billing based on data transfer. They might also generate a different type of event, `cache_invalidation`, with a property `number_of_files`. You can name title the `event_type` as needed, but for more insights check out how to [design billable metrics](/guides/get-started/core-concepts/create-billable-metrics/). * **properties** All keys and values in the `properties` map should be represented as strings, even though the values are often numeric. This prevents the loss of precision that often occurs in systems that use floating point numbers. Internally, Metronome uses arbitrary precision decimals to provide exact results of computation. Again, we advise sharing more data here than you might need initially so you can flexibly utilize this later on if need be. ## Queue and retry​ If usage events are lost on their way to Metronome, you’ll lose revenue. If you're sending events through the API, you need to be resilient to failures such as network issues or process crashes. A good way to gain this resilience is to put your usage events on a reliable queue such as [Amazon SQS](https://aws.amazon.com/sqs/) or [RabbitMQ](https://www.rabbitmq.com/), and have a process pull from that queue and push events to Metronome. If your call to the Metronome `/ingest` endpoint fails with a network error or a `5xx` HTTP status code, some of your events may have been ingested, but others may not. Always retry a failed call to `/ingest` until you receive a `200` status code. The unique `transaction_id` in each event prevents duplicate processing, so retries are always safe. If your call to the Metronome `/ingest` endpoint fails with a `429` HTTP status code, you have exceeded one of our rate limits. In this case, you should back off and retry the call after a delay. If the request continues to be rate-limited, wait for an exponentially increasing amount of time between retries. **AVOID AUTO-RETRIES ON 4XX** If a call to `/ingest` fails with a `4xx` HTTP status code (besides `429`), this indicates an issue with the payload. **Do not** automatically retry such a call. Instead, put the event aside in a [dead letter queue](https://en.wikipedia.org/wiki/Dead_letter_queue) and trigger an alarm so you can investigate the failure and resolve the issue. ## Message queue logging​ When first integrating with Metronome, it's helpful to enable logging in your message queue. This lets you audit exactly what usage events are being sent to Metronome. Also enabling logging any time you make a change to your usage events. ## Trial ingestion resilience​ To test your system’s response to elevated error rates from Metronome’s API, Metronome can set up an automatic failure rate of your choice (we recommend 20%). Contact us via the [Metronome support portal](https://support.metronome.com/) to specify the % failure rate, when to enable and disable the test, and if you'd like to apply it to your sandbox or production instance. ### Aggregation​ A billable metric aggregates over a single property by default. For example, if you're an email sending service, you might have a usage event that looks like: ```json theme={null} { "event_type": "email_sent", "properties": { "num_recipients": "8", "size": "1000" }, // ... } ``` Already, this event supports charging customers based on how many emails they sent or the maximum size of an email. For further aggregation, like total data sent (`num_recipients` \* `size`), use [SQL-based billable metrics](/guides/get-started/core-concepts/billable-metrics-sql-editor/). ## Heartbeat event idempotence​ Usage events typically fall into one of two categories: an event that occurs when a user takes some action, or a periodic "heartbeat" that measures the current state—a common approach in infrastructure services. For example, a service selling computation might send a per-node heartbeat to Metronome each minute describing the CPU and disk utilization on that node. These events could be aggregated into the metrics "CPU minutes" and "gigabyte minutes." It's important for heartbeat events to ensure that usage is only counted once. This is accomplished by choosing a deterministic `transaction_id` for duplicate events to have the same ID. Metronome guarantees that only one event with a given `transaction_id` is processed. In the example of a per-node per-minute heartbeat, you might structure a transaction ID as follows: ```bash theme={null} _ ``` where `unix_now()` is a function that returns the number of seconds since the [Unix epoch](https://en.wikipedia.org/wiki/Unix_time). By including both the node ID and a minute-granularity timestamp in the transaction ID, it's guaranteed that duplicate events from the same node in the same minute is ignored. Using this type of `transaction_id` means you also don't have to worry about sending events too often. We recommend sending *two or more heartbeats* per measurement period. Duplicates are safely ignored, and by using this approach, you decrease the risk of missing a measurement period due to timer imprecision or a temporary delay. **CHANGES TO USAGE EVENTS MAY CAUSE BREAKAGES** Usage events are designed to target very specific billable metrics, so if the data structure changes, it could prevent downstream metrics from being properly recorded. It's best to contact us via the [Metronome support portal](https://support.metronome.com/) any time you are adjusting the structure of your usage events. We can help validate and test the change with you to avoid any disruption. ## Ensure Metronome does not block critical paths Metronome has been expressly designed to use safely in the most critical parts of your application. In accordance with availability best practices, we suggest verifying that Metronome is not a blocker in your customer creation path. Since Metronome can match events sent at any time before or after customer creation using ingest aliases, we recommend creating the customer in your system first—then creating the matching customer record in Metronome asynchronously. # Plan your billing architecture Source: https://docs.metronome.com/guides/implement-metronome/planning-your-billing-architecture Start asking the right questions to ensure your billing architecture is built for success today and into the future. Building a billing system that can scale with your business involves more than just choosing the right platform - it requires thinking through how billing will integrate with your technical scale, product, operations, and customer experience. The companies who establish billing as a strategic advantage think through these questions early and often, not because they're locked into their answers forever, but because understanding how approaching these decisions sets you up for both immediate success and rapid iteration as you grow. Getting billing right is an iterative process, and starting with the right foundation means you can adapt quickly as you learn what works. The questions below will help you architect a billing system that scales with your business's success rather than constraining it. ## 1. Define Your Value Exchange Before diving into technical implementation, get crystal clear on the core value proposition that drives your pricing. If you already have a usage-based pricing model, you've likely worked through some of these decisions—but revisiting them regularly helps ensure your billing evolves with your product. ### Key questions include: * **What business outcome do you enable for customers?** Here are a few examples: * Data companies help organizations make better decisions. More access to quality data = more quality decisions. * AI coding tools help teams ship features faster. More AI conversations = more product velocity. * **What specific activities or resources drive that outcome?** Consider all the ways customers interact with your platform: API calls, compute time, storage consumed, predictions generated, or seats occupied. * **How should you structure your pricing around this value?** Your pricing model should connect the business outcome from question 1 with the activities from question 2. * **How often will this pricing structure change?** AI companies may need frequent adjustments due to underlying provider rate changes, while enterprise software typically requires pricing stability to honor existing contracts. ## 2. Map Your Data Foundation Usage-based billing is only as reliable as the data that feeds it. Having the right data foundation allows you to adapt your pricing model, add new product tiers, and scale across markets without rebuilding your entire billing infrastructure. ### Key questions include: * **Where does your usage data originate?** Common sources include application logs, infrastructure metrics, third-party APIs. Figure out how to reliably get this data to your billing system. * **How frequently is this data generated and how often does it change?** This determines how often you should send data to your billing system—real-time events, hourly batches, or daily aggregations. * **What's the volume and velocity?** Peak usage scenarios determine your infrastructure requirements * **What pricing dimensions do you need to support?** If you're pricing differently by region, customer tier, or product feature, ensure your data includes these grouping keys so your billing system can apply the correct rates. * **What supplemental information helps customers understand their spend?** Consider and send meaningful context like project names, user roles, or feature categories that make bills interpretable and actionable. ## 3. Choose Your Commercial Model Your billing architecture must align with and support how customers actually buy and consume your product. ### Key questions include: * **For self-serve customers, should usage be purchased upfront or billed in arrears?** Prepaid credits reduce fraud risk but require different cash flow management than post-usage billing * **How do seats and usage interact in your model?** Consider whether credits scale with seat count, if usage quotas are tied to subscription tiers, or if they operate independently * **For sales-led deals, what contract structures do you need to support?** Enterprise customers often require custom commitments, overages, ramp periods, and multi-year terms * **What happens when customers exceed their limits?** Your commercial model determines whether you throttle service, allow overages, or require immediate payment * **How do you handle different customer segments?** Startups, mid-market, and enterprise customers often need different pricing structures and payment terms within the same product Looking for guides to build your commercial model? ## 4. Design Your Data Distribution Modern billing isn't just about generating invoices—it's about putting usage data to work across your entire business. ### Key questions include: * **Where will customers see their usage, and how current must this data be?** If usage data appears in your product, ensure your billing system can deliver it via API with the freshness your customer experience requires. * **What granularity do customers need?** Make sure you can slice and dice the data to match customer expectations—detailed breakdowns require more complex query capabilities. * **How will sales teams access usage data?** Sales teams need usage insights for account management and compensation calculations. Plan for CRM integrations and custom reporting capabilities. * **What revenue recognition requirements exist?** Complex usage models create rev-rec challenges that require careful data handling and audit trails. * **Does your product need real-time billing notifications?** Consider webhook requirements for balance alerts, tier changes, and payment events that trigger immediate product actions Explore reporting in Metronome ## 5. Understand the System in Motion Usage-based billing is a dynamic system that requires ongoing operational management. Understanding how your billing platform behaves during changes, errors, and unexpected events is critical for maintaining customer trust and business continuity. ### Key questions include: * **What's your exposure to runaway usage?** Understanding the maximum potential impact from a single customer or incident helps you set appropriate safeguards * **How do you execute pricing changes?** Consider scheduling requirements, rollout timelines, and how long implementation takes across your customer base * **How do you audit platform actions?** Clear logs of billing calculations, price changes, and system modifications are essential for troubleshooting and compliance * **How do you recover from data or pricing errors?** When usage reporting fails or incorrect prices are applied, what's your process for correction and customer communication * **How do you handle traffic spikes?** Peak usage periods stress every part of your billing infrastructure—ensure your data ingest, alerting systems, and downstream processes can all scale together ## Conclusion The billing architecture decisions you make today will either enable or constrain your growth for years to come. The companies that scale successfully treat billing as a core product capability, not an afterthought. Ready to move from planning to building? Check out our [Getting to an Invoice](/guides/get-started/metronome-dashboard-quickstart) guide or our launch guides to start implementing your system. # Metronome go-live checklist Source: https://docs.metronome.com/guides/implement-metronome/production-checklist A go-live readiness checklist to validate your Metronome billing integration before launching in production. ## Validate usage and metering Invoice accuracy starts with usage ingestion. Verifying and matching required [usage event](/guides/events/design-usage-events) fields to active [billable metrics](/guides/get-started/core-concepts/create-billable-metrics/) ensures customers are charged what they used. Verify and check that: * all required event [fields](/api-reference/usage/ingest-events) are present: * `transaction_id` * `customer_id` (or alias) * `timestamp` * `event_type` * `properties` Follow a maximalist approach for properties: send as much metadata as possible, even if not pricing-relevant today, to future-proof your integration. * [idempotency](/api-reference/idempotency) is enabled for ingest events via [`transaction_id`](/guides/get-started/core-concepts/send-usage-events#heartbeat-event-idempotence%E2%80%8B). Visit the docs [here](/guides/get-started/core-concepts/send-usage-events#heartbeat-event-idempotence%E2%80%8B) for guidance on choosing a good `transaction_id`. * billable metrics are active and correctly match events by sampling Metronome’s [searchEvents](/api-reference/usage/search-events) endpoint. * usage events are queued through a reliable message queue (e.g., SQS, RabbitMQ) and that backdated usage up to 14 days is correctly ingested. * the ingestion pipeline is load tested to handle expected peak throughput. * fault injection tests are performed by simulating ingestion failures. Coordinate with Metronome if you need help setting this up. *** ## Confirm pricing and product setup Pricing accuracy is critical. Double-check that [rate cards](/guides/get-started/core-concepts/create-manage-rate-cards) and overrides in production reflect your intended setup so invoices remain consistent and predictable. Verify and check that: * the correct [products](/guides/get-started/core-concepts/create-products-contracts) (usage, composite, subscription, fixed) are being used; and configure tags, conversions, and group keys. * usage products are mapped to the intended billable metric. * the rate card is correct (currency, products, tiers/changes). *** ## Provision customers and contracts [Customers](/guides/get-started/core-concepts/provision-customer) must exist in Metronome and be linked to [contracts](/guides/get-started/core-concepts/provision-contract) for billing to start. This mapping ensures all usage is attributed to the right account with the right pricing. Verify and check that: * customers are created and, optionally, the ingest aliases are mapped correctly. * contracts are provisioned against the correct rate card and billing frequency. *** ## Verify invoicing and payment flows Customers expect smooth, accurate billing. Confirm [invoices](/guides/get-started/core-concepts/how-invoicing-works) and payments are flowing correctly before launch. Verify and check that: * that the invoice lifecycle is understood by your teams (draft → grace period → finalized). * that the `invoice.finalized` webhook is enabled and tested. * the delivery path is confirmed for your chosen [integration](https://metronome.com/integrations). ## Secure production environment Before launch, ensure that you’re running against production credentials, not sandbox. Using the correct [API tokens](/api-reference/authorization) gives you the foundation for secure, auditable billing that finance can reconcile and trust. Verify and check that: * the production API token is created and stored securely. * IP [allowlisting](/guides/platform-configuration/allowlist) is enabled, if required. * all API endpoints point to production URLs (`https://api.metronome.com`) *** ## Configure webhooks and API error handling Billing is only reliable if your system knows when things go wrong or statuses change. [Webhooks](https://docs.metronome.com/developer-resources/use-api/webhooks) keep your systems in sync (invoice finalization, alert triggers), and retry/backoff/error-handling on API calls ensures no usage or revenue is lost. Verify and check that: * the webhook endpoint is online and secured with signature verification using your Metronome webhook secret. * webhook processing is idempotent (safe on duplicate deliveries). * your retry/backoff policy is functional: retry with exponential backoff on 429/5xx status or network errors (the Metronome SDK has this retry/backoff behavior by default). * you have error handling for 4xx responses or errors raised by the Metronome SDK: DLQ + alert on these. *** ## Set up monitoring You can’t improve what you can’t see. Alerts keep you ahead of customer balance issues. Verify and check that: * spend, credit, and commit alerts are configured. * webhook notifications are firing for alerts in a timely manner. * monitoring is in place on webhook delivery and ingest error rates. *** ## Configure data export Data Export provides an auditable record of invoices, usage, and customer data outside Metronome. Enabling it ensures finance and RevOps can reconcile billing independently. Verify and check that: * Data Export is enabled for your production environment. * the export destination (e.g., warehouse, S3) is configured and receiving data. * sample exports contain the expected objects (invoices, customers, usage). * reconciliation processes are defined so finance can validate invoice data against exported usage. *** ## Run final end-to-end test Finally, simulate one end-to-end cycle in production. This gives confidence that invoices, totals, and payments line up in the real environment, to avoid exposing customers to errors. * Verify and check that sandbox-to-production migration is complete. * Run a production dry run with a test customer: send events → confirm invoice totals → verify webhook → confirm successful payment processing. * Document rollback procedures in case of critical issues. # Import existing invoices Source: https://docs.metronome.com/guides/invoices/invoice-optimization/import-existing-invoices Metronome offers a unified source of truth for your customers' billing history, even if you initially provisioned them outside of Metronome. You can easily import existing contracts and invoices into Metronome. This guide describes how to import an example contract and its corresponding invoices with the Metronome API. You can also use the Metronome SDK to import existing invoices. ## Use case The fictional company used in this guide, called Acme Inc, is a new Metronome client. In this example, today's date is August 15, 2024. Acme Inc has a contract outside of Metronome with a monthly billing schedule that started on June 1, 2024. Invoices for June and July were already issued outside of Metronome. ## Create the contract First, create the contract using the `/contracts/create` endpoint, entering the original contract details (for example, starting commit/credit balances and start date). Set the `usage_statement_schedule.invoice_generation_starting_at` field to indicate when Metronome should begin generating invoices. In our example, that date is August 1, 2024, since the customer hasn't been billed for August yet. ```http theme={null} POST /v1/contracts/create HTTP/1.1 Host: api.metronome.com Authorization: Bearer Content-Type: application/json { "customer_id": "", "rate_card_id": "", "starting_at": "2024-06-01T00:00:00.000Z", "usage_statement_schedule": { "frequency": "monthly", "invoice_generation_starting_at": "2024-08-01T00:00:00.000Z" } } ``` With the contract created, Metronome generates a draft invoice for August. No invoices are created for June and July. ## Import the invoices After creating the contract, import the corresponding invoices with the `/contracts/createHistoricalInvoices` endpoint. All you'll need is the quantities for each line item on the invoice. Metronome combines these with the unit prices specified on the contract to calculate the total amount on the invoice and the effects on the customer's credit and commit balances. ```http theme={null} POST /v1/contracts/createHistoricalInvoices HTTP/1.1 Host: api.metronome.com Authorization: Bearer Content-Type: application/json { "invoices": [ { "customer_id": "", "contract_id": "", "credit_type_id": "", "inclusive_start_date": "2024-06-01T00:00:00.000Z", "exclusive_end_date": "2024-07-01T00:00:00.000Z", "issue_date": "2024-07-03T00:00:00.000Z", "usage_line_items": [ { "product_id": "", "inclusive_start_date": "2024-06-01T00:00:00.000Z", "exclusive_end_date": "2024-07-01T00:00:00.000Z", "quantity": 10 } ] }, { "customer_id": "", "contract_id": "", "credit_type_id": "", "inclusive_start_date": "2024-07-01T00:00:00.000Z", "exclusive_end_date": "2024-08-01T00:00:00.000Z", "issue_date": "2024-08-03T00:00:00.000Z", "usage_line_items": [ { "product_id": "", "inclusive_start_date": "2024-07-01T00:00:00.000Z", "exclusive_end_date": "2024-08-01T00:00:00.000Z", "quantity": 20 } ] } ], "preview": true } ``` **TIP** Use the `preview` option to perform a dry run of the import to verify any differences between the existing and imported invoices before saving them. Access imported invoices on the **Contracts** page in the Metronome app or with the API. ## (Optional) Import hourly or daily breakdowns To use Metronome to retrieve hourly or daily breakdowns of customer usage and costs, specify time-windowed quantities by populating the `subtotals_with_quantity` field of the line item in lieu of the `quantity` field. Specify the `breakdown_granularity` of the invoice. When generating the invoice for the entire billing period, Metronome sums up the subtotals of each window. ```http theme={null} POST /v1/contracts/createHistoricalInvoices HTTP/1.1 Host: api.metronome.com Authorization: Bearer Content-Type: application/json { "invoices": [ { "customer_id": "", "contract_id": "", "credit_type_id": "", "inclusive_start_date": "2024-06-01T00:00:00.000Z", "exclusive_end_date": "2024-07-01T00:00:00.000Z", "issue_date": "2024-07-03T00:00:00.000Z", "breakdown_granularity": "day", "usage_line_items": [ { "product_id": "", "inclusive_start_date": "2024-06-01T00:00:00.000Z", "exclusive_end_date": "2024-07-01T00:00:00Z", "subtotals_with_quantity": [ { "inclusive_start_date": "2024-06-01T00:00:00.000Z", "exclusive_end_date": "2024-06-02T00:00:00.000Z", "quantity": 1 } ] } ] } ], "preview": true } ``` **INFO** Metronome doesn't send imported invoices to the Stripe integration. This prevents sending duplicate invoices to customers. # Issue credit memos Source: https://docs.metronome.com/guides/invoices/invoice-optimization/issue-credit-memos This use case describes how to issue customer credit memos for future and historical billings. Metronome focuses on the complexities of usage-based rating at scale, in real time. For most Metronome clients, accounts receivable (A/R) functions are handled upstream or downstream from Metronome in an Enterprise Resource Platform (ERP) or Customer Relationship Management (CRM) application. While Metronome provides an invoice that represents the charges and commitment draw-downs related to usage, there's no corresponding credit memo entity that you'd typically see in an ERP. That said, there are a variety of ways to handle adjusting a customer's A/R using Metronome. This doc explores some scenarios that explain how to adjust a customer's A/R in Metronome or in your A/R system. ## Credit future billings Credit memos can help resolve customer disputes. Rather than adjusting a past transaction or invoice with a credit memo, you can issue the customer a credit towards future billings. To accomplish this, first decide if you want to offer a customer-level credit or a contract-specific credit. The distinction between the two is that customer-level credits can be used against any existing contract associated with their account instead of a single contract. ### Example: Customer satisfaction credit Companies give customer satisfaction credits to appease an unsatisfied customer. Typical reasons for this include a poor in-app customer experience, customer complaints, or to credit for downtime and unavailability. As an example, assume that your application, which provides access to an AI model, was unavailable for an hour during the past billing period. A customer calls to express their frustration with the unavailability, explaining how it led to a loss of revenue and potential customer churn. To satisfy the customer, you agree to provide a \$100 credit towards future billings. #### Create a credit To create a customer-level credit with the Metronome API, use the [Create a Credit](/api-reference/credits-and-commits/create-a-credit) action. As the customer agreed to receive a \$100 credit for the hour of downtime, create the credit for an *amount* of 10000 (for USD, amounts are in **cents**, so 10000 = \$100.00). Use today's date as the starting date and the date you want the customer to use this credit by as the ending date. To grant them a recurring credit, create a separate `schedule_item` element for each billing period you want to grant them credit for. USD amounts are always in cents. Other supported currencies use whole units. See [currency denomination](/guides/pricing-packaging/make-pricing-changes/use-currency-custompricingunits#currency-denomination) for details. This call shows an example of the create a credit action: ```json theme={null} { "customer_id": "13117714-3f05-48e5-a6e9-a66093f13b4d", "name": "My Credit", "priority": 5, "product_id": "f14d6729-6a44-4b13-9908-9387f1918790", "access_schedule": { "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "schedule_items": [ { "amount": 10000, "starting_at": "2024-09-01T00:00:00.000Z", "ending_before": "2020-09-30T00:00:00.000Z" } ] } } ``` If a customer has multiple active credits on their account/contract, set an appropriate `priority`. The priority dictates which credits get burned down first. To learn more, see [Manage credits and commits](/guides/pricing-packaging/apply-credits-and-commits/create-a-pre-paid-commit). `credit_type_id` is the currency that the credit should be entered in. Find the list of currency IDs in the [Metronome app](https://app.metronome.com/) under **General Settings → Pricing Units.** **INFO** The ID for USD is `2714e483-4ff1-48e4-9e25-ac732e8f24f2`. `product_id` is the ID of the product you want to **show** on the invoice. In the example, you have a product called `Customer Satisfaction Credit`. If you want the credit to apply to specific products on the account instead of any and all products, include those IDs in the `applicable_product_ids` container. ## Credit historical billings If the customer isn't amenable to a credit against future billings, you have different ways to correct the recorded revenue, outlined in these examples. ### Example: Invoice correction (and reduction in revenue) You may find yourself in a situation where billings are incorrect. You need to fully reverse the charges AND reduce the revenue associated with those charges. For example, a customer gets set up incorrectly to receive and get billed for products they didn't order. In other situations, the customer becomes completely unsatisfied with the service or product shortly after signing up. They want you to relieve them of any outstanding charges for that service. The end result is to reverse the charges and revenue as if they never occurred in the first place. In this case, since Metronome is not the management system for customer A/R, create a credit memo directly in the system that manages your A/R. As a result, the adjusted customer invoice and the invoice line amount in Metronome will vary from that in the invoicing system. This discrepancy is acceptable from an audit perspective as the credit memo provides the necessary audit record(s) to justify the difference. ### Example: Customer has incorrect usage (current billing period) If you notice that a customer has incorrect usage for the current billing period with an invoice in the `DRAFT` state, you can correct this in Metronome by passing in an event that negates the original usage. To do so, pass an event with a *negative* quantity/value that matches the the billable metric of the product you want to credit. For example, if your billable metric aggregates by a property of `token_count`, where you normally pass positive values, negate the relevant usage by passing a negative value to `token_count`. For example: ```json theme={null} { "timestamp": "2024-07-30T23:46:24.343000+00:00", "transaction_id": "e88c64c4-7b14-4703-8d5b-df514506cba9", "customer_id": "43ae3f41-480b-412b-9b05-1c4d11169c08", "event_type": "output_tokens", "properties": { "project_id": "Project 1", "token_count": "-50" } } ``` ### Example: Customer has incorrect usage (previous billing period) If you notice that a customer has incorrect usage for a previous billing period with an invoice in the `finalized` state, you can grant the customer a credit towards future billings or create a credit memo directly in your customer A/R management system. Metronome doesn't allow the correction/adjustment of usage events for finalized invoices. ### Example: Credit and re-bill In situations where the *entire* invoice is incorrect, you should credit and re-bill. If your A/R system doesn't support invoice voiding or cancellations, you need to create a credit memo. To do this in Metronome: 1. Negate the incorrect usage following the steps in the previous example. 2. After you negate the original usage, submit the corrected usage records. 3. Void the incorrect invoice with the API ([Void Invoice](/api-reference/invoices/void-an-invoice)) or in the Metronome app. To void with the Metronome app, navigate to the invoice in question, select the overflow menu, and choose **Void Invoice.** Take note of the Invoice ID. Void invoice screenshot **VOIDING IN METRONOME DOESN’T VOID DOWNSTREAM** Voiding the invoice in Metronome does **not** automatically void invoices in any downstream application. You must perform a similar function in that application manually. 4. After the previous invoice gets voided, regenerate a new invoice with the API [(Regenerate Invoice)](/api-reference/invoices/regenerate-an-invoice) or in the Metronome app. This causes Metronome to recalculate a new invoice based on the associated usage sent. If using the Metronome Stripe integration, this new invoice gets sent to Stripe automatically. **34 DAY WINDOW** Metronome has a limit of **34 Days** where you can submit historical usage. If the credit and re-bill action you want to take is *beyond* 34 days in the past, your only option is to complete the voiding, canceling, and regeneration of invoices directly within your invoicing and customer A/R application. ### How Metronome handles refunds Customer refunds, defined as the act of sending back all or a portion of a customer's payment, are outside the scope of current Metronome functionality. The exact steps to refund a customer depend on your existing technology stack. They typically get handled through your ERP, CRM or directly within your chosen payment processor application. # Overview Source: https://docs.metronome.com/guides/invoices/overview Metronome offers targeted solutions for invoicing to provide best-in-class support for each billing motion and distribution channel its clients support: * **Stripe Invoicing:** Metronome natively integrates with Stripe to support client's invoicing needs. Integrate with Stripe invoicing and take advantage of Stripe Tax, dunning, and other features within the Stripe product suite. * **Marketplace Invoicing:** Metronome's out-of-the-box integration that automates the metering to and creation of invoices in AWS, Azure, and GCP. This integration supports all charge types in Metronome - enabling you to launch a new pricing plan and immediately make it available via marketplace distribution channels. No third-party integrator required. * **ERP Invoicing:** Metronome provides out-of-the-box and custom integrations to ERPs. Optimized for clients that bill their SLG business or execute revenue workflows inside of ERPs. Seamlessly sync transactions for collection and close your books, complaint with ASC 606 guidelines. Metronome believes that optionality and control is important. Some organizations do not need the power of NetSuite invoicing and prefer simpler, integrated solutions. Others, with complex enterprise contracting requirements and revenue processes, need ERP systems. With Metronome, you do not need to choose. Use each capability as it makes sense for your business. ### Explore invoicing solutions available in Metronome Native integration optimized for most billing use cases. Native metering integration to AWS, Azure, and GCP Marketplaces. Native integration designed to support ERP billing and revenue workflows # Set threshold notifications on credit and commits Source: https://docs.metronome.com/guides/pricing-packaging/apply-credits-and-commits/alerts Threshold notifications on credits and commitments can power entitlement, upsell use cases, and more. For example, for some business models where PayGo customers must prepay for all usage and cannot pay in arrears, customers should be cut off from further using the product if there’s no remaining credit or commit balance. Threshold notifications are just one of the many mechanisms Metronome provides to [manage access to your product](/guides/customers-billing/manage-customers/manage-product-access). It’s also useful to know when a customer has almost exhausted their commitment so that sales can drive renewal or upsell conversations. For example, if 90% of the commitment was used in the first few months of a year-long contract, it benefits both parties to renegotiate and increase the size of the commitment. Metronome supports [notifying](/guides/customers-billing/set-up-notifications/create-and-manage-notifications) on credit and commit remaining balance, percent remaining balance, and days remaining. Metronome supports using custom fields to filter notifications down to a subset of commits or credits. For example, to add a threshold notification for a customer that fires when their free trial credit is fully consumed: 1. Add a `credit_type` [custom field](/api-reference/custom-fields) to the credit entity and set the relevant value on each object. For example, `free_trial`. 2. Navigate to **Notifications** > click **Add Notification**. 3. Name the notification. 4. Select the **Contract credit balance** notification type and enter a \$0 value. 5. Click **Advanced filters** > select `credit_type` as the custom field key and enter `free_trial` as the value. 6. Select the customers to whom this notification should apply. # Apply credits and commits to contracts Source: https://docs.metronome.com/guides/pricing-packaging/apply-credits-and-commits/create-a-pre-paid-commit You can grant free credits and encode prepaid and postpaid commits on Metronome contracts. The balance of these credits and commits, and their application against draft invoices, updates continuously in real time as customers use your product. Credits and commits power a range of business models, from product-led growth motions to complex enterprise contracts. ## How credits and commits work​ Credits and commits in Metronome are flexible on these dimensions: * **Effective time period**: Credits and commits have an `access_schedule` that defines spend allotments associated with one or many date ranges. Define the date ranges by any hour-aligned time, and only usage falling within the range consumes the credit or commit. * **Applicable products**: Specify a subset of products, defined by product IDs (`applicable_product_ids`) or product tags (`applicable_product_tags`), to consume a credit or commit. Applicable product tags ensure that new products launched in an existing family can consume the correct commits automatically. Alternatively use the [specifiers](/guides/pricing-packaging/apply-credits-and-commits/target-credit-and-commits) field to target usage of credits and commits based on pricing group values or presentation group values. * **Invoice schedule**: With prepaid commits, define a one-time invoice or break the payment into multiple invoices on any schedule. Customize the amount invoiced for any prepaid commit. * **Custom fields**: Tag credits and commits with metadata useful for downstream workflows like [alerting](/guides/customers-billing/set-up-notifications/create-and-manage-notifications), [data reconciliation](/guides/reporting-insights/financial-reporting/reconcile-data), and [revenue recognition](/guides/reporting-insights/financial-reporting/revenue-recognition). For example, get alerted when the remaining balance of credits with the custom field `free_trial`reaches 0. Credits and commits are always associated with a fixed product. This is because products are used to invoice. In the case of commits, the product is used to invoice the prepaid commit amount or the postpaid commit true-up amount. It contains metadata like a name and ID, which enables you to query things like, what's the revenue for this commit's product across my customers? ## Grant a free credit​ Credits give customers a monetary amount of free usage. Common scenarios for free credits include free trials, reimbursement for downtime (SLA credits), and promotions. For USD, all monetary amounts in the API are in **cents** (for example, `1000` = \$10.00). Other supported currencies use whole units. See [currency denomination](/guides/pricing-packaging/make-pricing-changes/use-currency-custompricingunits#currency-denomination) for details. As a common scenario, clients grant free credits to a customer where the customer can use the credits during the access period for all active contracts. Learn how to [provision customers](/guides/customers-billing/manage-customers/provision-a-customer) with contracts. To grant credits to a customer through the [Metronome app](https://app.metronome.com/): 1. Go to **Customers** > select the customer > Contract commits and credits > click **Add credit**. 2. Link the credit to a fixed product by selecting the Credit product from the dropdown. Credits and commits in Metronome are always associated with a fixed product. For example, you can create separate products for a free credit, SLA credit, and promotion credit. 3. (Optional) Add an internal description to explain why you’re granting the credit. 4. (Optional) If the credit can only be consumed by a subset of usage, specify applicable product IDs or applicable product tags. If omitted, all usage, subscription, and composite charges can consume credits. 5. (Optional) If the credit should only be consumed by a subset of the customer’s contracts, specify applicable contract names or IDs. If omitted, usage tied to all contracts consumes the credit. 6. Create an access schedule. An access schedule consists of one or more segments, each defined by a date range and associated with an amount. For example, to grant a \$10/month credit for three months, create three segments in the access schedule: 7. (Optional) Specify the rollover percentage of the credit. In the case of a contract renewal, specify what percent of the initial balance of the credit should roll over to the new contract. Learn more about [contract transitions](/guides/customers-billing/manage-customers/manage-customer-lifecycle). Credit Access Schedule Example 7. Define the priority of the credit. If a customer has multiple credits or commits that could apply against usage, the priority dictates the order in which the credits and commits are consumed. Lower priorities get consumed first. For example, you may want all credits to be consumed fist before consuming any commits. Read about the full list of [prioritization rules](/guides/pricing-packaging/apply-credits-and-commits/prioritization-rules). This example API request shows how to create a free credit: ```bash theme={null} curl https://api.metronome.com/v1/contracts/customerCredits/create \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "13117714-3f05-48e5-a6e9-a66093f13b4d", "name": "SLA Credit", "priority": 1, "product_id": "f14d6729-6a44-4b13-9908-9387f1918790", "access_schedule": { "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "schedule_items": [ { "amount": 1000, "starting_at": "2024-10-01T00:00:00.000Z", "ending_before": "2024-11-01T00:00:00.000Z" }, { "amount": 1000, "starting_at": "2024-11-01T00:00:00.000Z", "ending_before": "2024-12-01T00:00:00.000Z" }, { "amount": 1000, "starting_at": "2024-12-01T00:00:00.000Z", "ending_before": "2025-01-01T00:00:00.000Z" } ] } }' ``` ## Issue a prepaid or postpaid commit​ Prepaid and postpaid commits represent an agreement by a customer to spend a dollar amount over a period of time. Prepaid commits get paid in advance, while postpaid commits get paid in arrears. While usually associated with contracts, you can also encode commits at a customer level, where they’re consumed by all or a subset of contracts for that customer. ### Prepaid commits​ Prepaid commits get paid in advance. For example, imagine a customer committed to \$10,000 of spend over the lifetime of their contract, for which they get charged in two invoices: one for \$4,000 and one for \$6,000. The contract spans from October 01, 2024 to October 01, 2025. To add a prepaid commit to a contract in the Metronome app: 1. When creating a contract, click **Add commit.** 2. Link the commit to a fixed product. 3. (Optional) Add an internal description explaining the reason for granting the commit. 4. (Optional) If the commit can only get consumed by a subset of usage, specify applicable product IDs or applicable product tags. If omitted, all usage, subscription, and composite charges can consume the commit. 5. Create an access schedule. An access schedule consists of segments, each defined by a date range and associated with an amount. For example, set the access schedule to October 01, 2024 to October 01, 2025, matching the term of the contract. 6. (Optional) Create an invoice schedule. This determines the cadence to bill your customer for the commit. * You can bill your customer for any amount in any number of installments. For example, create two invoice schedule segments: * One segment on October 01, 2024 for \$4,000 * Another segment on November 01, 2024 for \$6,000 * To capture the invoiced amount without generating an invoice for downstream billing providers, select the **Do not invoice** option after entering the invoice amount. 7. Define the priority of the commit. If a customer has multiple credits or commits that could apply against usage, the priority dictates the order in which the credits and commits are consumed. Lower priority commits get consumed first. 8. (Optional) Specify the rollover percentage of the commit. In the case of a contract renewal, specify what percent of the initial balance of the commit should roll over to the new contract. Learn more about [contract transitions](/guides/customers-billing/manage-customers/manage-customer-lifecycle). This example API call shows how to create a contract with the example prepaid commit: ```bash theme={null} curl https://api.metronome.com/v1/contracts/create \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "13117714-3f05-48e5-a6e9-a66093f13b4d", "rate_card_id": "d7abd0cd-4ae9-4db7-8676-e986a4ebd8dc", "starting_at": "2024-10-01T00:00:00.000Z", "commits": [ { "type": "prepaid", "product_id": "cc69a00a-fa8f-4ae6-afdb-703e63fb4777", "access_schedule": { "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "schedule_items": [ { "amount": 100000, "starting_at": "2024-10-01T00:00:00.000Z", "ending_before": "2025-10-01T00:00:00.000Z" } ] }, "invoice_schedule": { "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "schedule_items": [ { "amount": 400000, "timestamp": "2024-10-01T00:00:00.000Z" }, { "amount": 600000, "unit_price": 600000, "quantity": 1, "timestamp": "2024-11-01T00:00:00.000Z" } ] } } ] }' ``` ### Postpaid commits​ For postpaid commits, usage during the access period (defined by `access_schedule`) gets paid for in arrears. If the total amount paid during the access period is less than the committed amount, there’s a final true-up invoice on the `invoice_date`. For example, if a customer has a contract with a postpaid commitment to spend \$10,000 over the one-year contract term from October 01, 2024 to October 01, 2025, billed monthly, each month, the customer gets billed in arrears for usage incurred in that month. At the end of the contract, the customer spent a total of \$9,000. On the specified `invoice_date`, a true-up invoice for \$1,000 is issued to reach the commitment of \$10,000. To add a postpaid commit to a contract in the Metronome app: 1. When creating a contract, click **Add commit.** 2. Link the commit to a fixed product. 3. (Optional) Add an internal description explaining the reason for granting the commit. 4. (Optional) If the commit can only get consumed by a subset of usage, specify applicable product IDs or applicable product tags. If omitted, all usage, subscription, and composite charges can consume the commit. 5. Create an access schedule. By default, the access schedule is the term of the contract. You can allocate a proportion of spend to distinct time windows across the contract. In the example scenario, the access schedule is from October 01, 2024 to October 01, 2025. 6. Select the invoice date. The invoice date is the date when a true-up invoice gets issued if the actual spend falls short of the committed amount. By default, the invoice date is the end date of the contract, but you can customize it to any date after the access schedule. For the example scenario, the invoice date is October 01, 2025, the end date of the contract. * To capture the invoiced amount without generating an invoice for downstream billing providers, select the **Do not invoice** option after entering the invoice amount. 7. Define the priority of the commit. Prepaid commits and credits burn down first. If a customer has multiple postpaid commits that could apply against usage, the priority dictates the order in which the postpaid commits are consumed. Lower priority commits get consumed first. 8. (Optional) Specify the rollover percentage of the commit. In the case of a contract renewal, specify what percent of the initial balance of the commit should roll over to the new contract. Learn more about [contract transitions](/guides/customers-billing/manage-customers/manage-customer-lifecycle). This example API call shows how to create a contract with the example postpaid commit: ```bash theme={null} curl https://api.metronome.com/v1/contracts/create \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "13117714-3f05-48e5-a6e9-a66093f13b4d", "rate_card_id": "d7abd0cd-4ae9-4db7-8676-e986a4ebd8dc", "starting_at": "2024-10-01T00:00:00.000Z", "ending_before": "2025-10-01T00:00:00.000Z", "commits": [ { "type": "postpaid", "product_id": "1cca616f-d6c7-44d3-b02d-cfcc85f97fd6", "access_schedule": { "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "schedule_items": [ { "amount": 1000000, "starting_at": "2024-10-01T00:00:00.000Z", "ending_before": "2025-10-01T00:00:00.000Z" } ] }, "invoice_schedule": { "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "schedule_items": [ { "amount": 1000000, "timestamp": "2025-10-01T00:00:00.000Z" } ] } } ] }' ``` ## Provision recurring usage credits​ As part of a subscription or contract, organizations commonly allocate a fixed amount of usage to a customer. The amount generally scales with the tier of the plan, such as Good, Better, and Best. Organizations adopt this model to get the benefits of subscription with fixed recurring revenue and usage-based billing with collecting on overages. Model this behavior in Metronome by setting up a recurring credit or commit on a contract. ### Configure recurring credits or commits​ Similar to how you can issue individual credits and commits, you can also schedule the release of credits and commits on a recurring basis. With recurring grants, a new credit or commit is issued with a unique ledger attached to it at the start of each period. 1. For free usage with a \$0 cost basis, create a recurring credit. For paid usage, create a recurring commit. 2. Specify the credit or commit product that generates the invoice line item for the recurring charge. This product’s metadata, such as custom fields, is passed through to the invoice where the commit or credit is applied. 3. Specify which products the grant should apply to. If left blank, it applies to all products. Use product tags for easier configuration. 4. Specify whether unused credits and commits expire at the end of each period by defining the `commit_duration`. You can roll over the total amount of credits remaining for a number of periods. 5. Optionally update the recurrence schedule. It defaults to the usage schedule defined on the contract. **INFO** If a `recurrence_frequency` is set on the contract, the anchor date for the recurring commit will default to the `starting_at` of the commit. This means that if the contract start date and the recurring commit start date are distinct, the first period **will not** be prorated. 6. Define proration behavior. If left null, the default behavior is prorate any grants that don't cover a full period (`FIRST_AND_LAST`). 7. Optionally, define rounding behavior when commit access and invoice schedules are prorated. This can be used to only grant and charge whole-number amounts, for example. 8. To issue commit charges on the same invoice as the contract’s usage statement, specify that usage and scheduled charges should [consolidate on the contract](/guides/customers-billing/manage-customers/provision-a-customer#consolidate-usage-and-scheduled-invoices). ### Upgrade or downgrade a customer’s contract​ Customers may upgrade or downgrade to new tiers after familiarizing themselves with your product. To facilitate this, create a new contract using a [contract renewal](/guides/customers-billing/manage-customers/manage-customer-lifecycle#contract-renewal). This ends the current contract and all future recurring charges and generates a new contract with updated terms. If a customer is entitled to maintain their existing balance as part of the upgrade or downgrade, specify a **Contract Transition Rollover** of 100% when creating the initial contract. #### Upgrade at the start of new period​ To facilitate or schedule an upgrade at the start of a new billing period: 1. Create a new contract and set the start date to the start of the billing period. Specify the contract transition as a **Renewal** and pass the previous contract’s ID. 2. If a contract roll-over was specified for the recurring commit on the first contract, the remaining balance rolls over to the new contract based on this setting. The future recurring charges from the first contract are removed. The new contract generates a `FINALIZED` scheduled invoice for the first recurring commit. It also generates a new `DRAFT` usage invoice to meter usage for the first month. #### Upgrade mid-period​ To facilitate a mid-period upgrade: 1. Create a new contract and set the start date to today’s date. Specify the contract transition as a **Renewal** and pass the previous contract’s ID. 2. The commit amount for the first period will be prorated. 3. If a contract roll-over was specified for the recurring commit on the first contract, the remaining balance rolls over to the new contract based on this setting. The `DRAFT` usage invoice on the first contract will finalize with the usage up to that date. The new contract generates a new `DRAFT` usage invoice to capture usage from the rest of the period and a `FINALIZED` scheduled invoice with the prorated charge for the first recurring commit. #### Backdate an upgrade​ The benefit of backdating an upgrade is that the user only receives a single usage invoice during the billing period. To backdate an upgrade: 1. Create a contract and set the start date to the first day of the current billing period. Specify the contract transition as a **Renewal** and pass the previous contract’s ID. 2. This finalizes the current `DRAFT` usage invoice from the first contract. The updated service period starts and ends on the same day, meaning that usage from the open period moves to the new contract. 3. On the new contract, create a on-time commit that represents the discounted amount for the first period. The amount should be *(prorated total) - (amount paid on first contract)*. 4. Create a recurring schedule that starts on the second period of the contract on a move-forward basis. ### Recurring credit example​ Consider an example where a customer signs up for your company’s lowest tier plan on January 1st. This free plan gives them access to \$10 in free credits each month and access to the Basic products. If the customer doesn’t use their credits each month, they expire at the start of the next month. This example API call shows how to create the contract with a recurring free credit: ```bash theme={null} curl https://api.metronome.com/v1/contracts/create \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "", "rate_card_id": "", "starting_at": "2025-01-01T00:00:00Z", "name": "recurring-commit-contract", "commits": [], "custom_fields": { "contract_tier": "basic" } "recurring_credits": [ { "name": "recurring credit", "description": "recurring credit", "product_id": "", "access_amount": { "unit_price": 1000, "quantity": 1, "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2" }, "priority": 1, "commit_duration": { "unit": "periods", "value": 1 }, "starting_at": "2024-12-01T00:00:00Z", "rollover_fraction": 100 } ] }' ``` After using the product for a few weeks, the customer decides to upgrade their plan on January 21st while they have \$2 in remaining balance. This new plan costs \$20 a month. It gives them a \$30 usage allotment each month and access to the Premium feature set. As part of the new plan, the customer can roll over the commits to the next period if they don’t use it all. This example API call shows how to use a contract transition to create a new contract: ```bash theme={null} curl https://api.metronome.com/v1/contracts/create \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "", "rate_card_id": "", "starting_at": "2025-01-01T00:00:00Z", "name": "recurring-commit-contract", "commits": [], "custom_fields": { "contract_tier": "basic" }, "recurring_commits": [ { "name": "recurring commit", "description": "recurring commit", "product_id": "", "access_amount": { "unit_price": 3000, "quantity": 1, "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2" }, "priority": 1, "commit_duration": { "unit": "periods", "value": 2 }, "starting_at": "2024-12-01T00:00:00Z", "invoice_amount": { "unit_price": 2000, "quantity": 1, "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2" } "rollover_fraction": 100 } ] "transition": { "from_contract_id": "", "type": "renewal" } }' ``` Once the new contract is provisioned, the customer has the following balance: * \$2 in free usage rolled over from the first contract * \$10 from a paid commit with a cost basis of 0.67 ## How credits and commits work with invoices​ In Metronome, credits and commits are always applied against usage at a line-item level rather than the aggregate invoice level. This attribution creates the ability to more accurately recognize precommitted and overage spend against each product. On an invoice, line items are separated based on whether the usage draws down a commit, a credit, or is in overage. **INFO** The same usage can apply against only one commit or credit. For example, if you incurred \$500 of usage and have a contract encoded with a \$400 prepaid commit and a \$400 postpaid commit, the prepaid commit gets consumed first. \$400 of the usage fully consumes the prepaid commit. Then, the remaining \$100 counts toward fulfilling the postpaid commit. As postpaid commits get paid in arrears, the customer would still get charged \$100. This example invoice API response demonstrates a situation where a customer consumed \$10 of Data Storage during the billing period. Of the \$10, \$4 is covered by a prepaid commit, and \$6 is not covered by a credit or commit. In the invoice response, this results in 3 line items: * Usage covered by the prepaid commit, with a total of \$4 * Commit application line item, with a total of -\$4 * Usage not covered by a prepaid commit or credit (”Overage” line item), with a total of \$6 ```json theme={null} { "data": { "billable_status": "billable", "contract_custom_fields": {}, "contract_id": "222fd78f-c93d-4b11-bec8-a7b12b510214", "credit_type": { "id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "name": "USD (cents)" }, "custom_fields": {}, "customer_custom_fields": {}, "customer_id": "b61bf255-d6f2-49fc-a062-b32431e2d22d", "end_timestamp": "2024-11-01T00:00:00+00:00", "external_invoice": null, "id": "e1937b93-64a5-5117-99e1-eb963a71e764", "issued_at": "2024-11-02T12:00:00+00:00", "line_items": [ { "commit_custom_fields": {}, "commit_id": "fde728f0-af26-45c3-92f6-7587dedadef3", "commit_segment_id": "fc696ca9-58b6-49e1-b2dc-888d78acd00e", "commit_type": "PrepaidCommit", "credit_type": { "id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "name": "USD (cents)" }, "ending_before": "2024-11-01T00:00:00+00:00", "name": "Data Storage", "product_custom_fields": {}, "product_id": "c8dccd54-0ca8-4580-861d-1e26854ab2f1", "product_type": "UsageProductListItem", "quantity": 4, "starting_at": "2024-10-01T00:00:00+00:00", "total": 400, "unit_price": 100 }, { "commit_custom_fields": {}, "commit_id": "fde728f0-af26-45c3-92f6-7587dedadef3", "commit_netsuite_item_id": "1234", "commit_segment_id": "fc696ca9-58b6-49e1-b2dc-888d78acd00e", "commit_type": "PrepaidCommit", "credit_type": { "id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "name": "USD (cents)" }, "ending_before": "2024-11-01T00:00:00+00:00", "name": "Prepaid Commit applied", "product_custom_fields": {}, "product_id": "c8dccd54-0ca8-4580-861d-1e26854ab2f1", "product_type": "UsageProductListItem", "starting_at": "2024-10-01T00:00:00+00:00", "total": -400 }, { "credit_type": { "id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "name": "USD (cents)" }, "ending_before": "2024-11-01T00:00:00+00:00", "name": "Data Storage", "product_custom_fields": {}, "product_id": "c8dccd54-0ca8-4580-861d-1e26854ab2f1", "product_type": "UsageProductListItem", "quantity": 6, "starting_at": "2024-10-01T00:00:00+00:00", "total": 600, "unit_price": 100 } ], "start_timestamp": "2024-10-01T00:00:00+00:00", "status": "DRAFT", "total": 600, "type": "USAGE" } } ``` # Offer discounts on commits Source: https://docs.metronome.com/guides/pricing-packaging/apply-credits-and-commits/discounting-on-commits To generate more predictable revenue, companies prefer their customers to commit to spending thresholds. To incentivize customers to do so, companies can offer discounts for larger commitments. Metronome provides the flexibility to model these discounts in two primary ways: 1. Reduce the cost basis for the commit 2. Create commit-specific overrides on the customer contract For advanced billing structures, Metronome also supports a third way to discount commits: encoding *commit rates* on a rate card. ## Reduce the commit cost basis​ A common approach to discounting commits is to reduce the cost basis. As an example, an enterprise contract states that in exchange for a \$10,000 pre-committed amount, the customer receives a 20% discount when consuming the commit. One option for encoding this pricing model is to change the cost basis of the pre-committed amount. You can encode a 20% discount by granting the customer \$10,000 of spend, but only billing \$8,000. This example API call creates a commit with a \$10,000 access schedule but an \$8,000 invoice schedule: ```bash theme={null} curl https://api.metronome.com/v1/contracts/customerCommits/create \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "13117714-3f05-48e5-a6e9-a66093f13b4d", "type": "prepaid", "name": "Prepaid Commitment", "priority": 1, "product_id": "f14d6729-6a44-4b13-9908-9387f1918790", "access_schedule": { "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "schedule_items": [ { "amount": 100000, "starting_at": "2024-10-01T00:00:00.000Z", "ending_before": "2025-10-01T00:00:00.000Z" } ] }, "invoice_schedule": { "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "schedule_items": [ { "unit_price": 80000, "quantity": 1, "timestamp": "2024-10-01T00:00:00.000Z" } ] } }' ``` When using the cost basis to encode the discount, note: * The prices reflected on usage statements are not affected by the cost basis. The 20% discount when using the commit is not visible on the usage statement. * Using the cost basis only works when commit rates are a uniform percentage off, not when commit rates are completely distinct from list rates or have different per-product rates. * This discount method is suitable when the commit is prepaid, but not for postpaid commits, where the invoice schedule amount must match the access schedule amount. If your use case doesn't meet these criteria, you can use commit-specific overrides instead. ## Create commit-specific overrides​ An alternative way of granting a discount when consuming a commit is to apply *commit-specific overrides* to encode adjusted rates when consuming a commit. You can specify whether the override should apply when consuming **all commits and credits** (prepaid commits, postpaid commits, and credits) or **only specific commits or credits** (e.g. commit\_id A and recurring\_credit\_id B). You can create commit-specific multiplier, overwrite, or tiered overrides. You can use product IDs, product tags, pricing group keys, and presentation group keys to specify which line items should get an override. Commit-specific overrides are higher priority than non-commit-specific overrides. Overrides are prioritized using the following logic: 1. Commit-specific overwrite overrides. 2. Commit-specific multiplier overrides, prioritized with your contract's prioritization scheme (lowest multiplier or explicit). 3. Non-commit-specific (contract-level) overwrite overrides. 4. Non-commit-specific multiplier overrides, prioritized with your contract's prioritization scheme (lowest multiplier or explicit). **INFO** Commit-specific overrides are not prioritized based on the number of commits associated with an override. If you add a multiplier override that applies to all commits, and a multiplier override that applies only to commit B, these two overrides are prioritized based on normal prioritization rules (lowest multiplier or explicit). **INFO** Metronome provides functionality to target a commit-specific override to a specific `commit_id` or `recurring_commit_id`, `credit_id`, or `recurring_credit_id`. Use the field `any_commit_or_credit_ids` to limit the scope of a commit-specific override. If no specific credits or commits are targeted, the override will apply whenever usage burns down any prepaid commit, postpaid commit, or credit. ### Continued discount example As an example of overriding the commit on a customer contract, take this example with a discount on both the commit spend and additional consumption: * Your list rates for audio models are \$1 per million input tokens and \$2 per million output tokens. Both products are tagged with `audio`. * The customer committed to \$10,000 of prepaid spend on their contract (commit A). * The customer has negotiated prices when consuming the prepaid spend and after the commit has been fully consumed: * When consuming the commit, the customer gets 20% off list prices. * When not consuming the commit, the customer get 5% off list prices. To implement this in Metronome, add two overrides on the contract. The commit-specific override takes higher priority over any non-commit-specific overrides: * Override 1: 0.95 multiplier against the `audio` product tag * Override 2: 0.8 multiplier against the `audio` product tag when consuming commit A This example API request creates the contract, including the prepaid commit and commit-specific overrides. Notice the commit is referred to using a `temporary_id` to allow encoding both commits and commit-specific overrides on contract creation. ```bash theme={null} curl https://api.staging.metronome.com/v1/contracts/create \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "bc20325a-80a0-468e-868f-a2f28b972af8", "starting_at": "2024-10-01T00:00:00.000Z", "rate_card_id": "d7abd0cd-4ae9-4db7-8676-e986a4ebd8dc", "commits": [ { "temporary_id": "prepaid_commit_A", "type":"prepaid", "priority":1, "name":"Prepaid Commit A", "product_id":"f14d6729-6a44-4b13-9908-9387f1918790", "access_schedule": { "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "schedule_items": [ { "amount": 1000000, "starting_at": "2024-10-01T00:00:00.000Z", "ending_before": "2025-10-01T00:00:00.000Z" } ] }, "invoice_schedule": { "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "schedule_items": [ { "unit_price": 1000000, "quantity": 1, "timestamp": "2024-10-01T00:00:00.000Z" } ] } } ], "overrides": [ { "starting_at": "2024-10-01T00:00:00.000Z", "multiplier": 0.95, "type": "multiplier", "override_specifiers": [ { "product_tags": [ "audio" ] } ] }, { "starting_at": "2024-10-01T00:00:00.000Z", "is_commit_specific": true, "multiplier": 0.8, "type": "multiplier", "override_specifiers": [ { "commit_ids": [ "prepaid_commit_A" ], "product_tags": [ "audio" ] } ] } ] }' ``` ### Discount when consuming any commit or credit​ As another example of creating commit-specific overrides, take this example with a discount when consuming any commit: * Again, your list rates for audio models are \$1 per million input tokens and \$2 per million output tokens. * The customer has committed to \$3,000 of prepaid spend on their contract (commit A). The customer wants to leave open the option of adding more prepaid commits in the future. * The customer has negotiated prices when consuming commits: audio model input tokens are \$0.75 per million and audio model output tokens are \$0.889 per million. * When all commits are consumed, further usage of audio models use the list rate. To implement this in Metronome, add two overrides on the contract: * Override 1: overwrite override of \$0.75 on input tokens when consuming **any commit or credit** * Override 2: overwrite override of \$0.889 on output tokens when consuming **any commit or credit** This example API request adds both overrides by editing the contract: ```bash theme={null} curl https://api.staging.metronome.com/v2/contracts/edit \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "bc20325a-80a0-468e-868f-a2f28b972af8", "contract_id": "82a884c5-5e3e-47ae-b056-63b6f3a84674", "add_overrides": [ { "starting_at": "2024-10-01T00:00:00.000Z", "product_id": "c8dccd54-0ca8-4580-861d-1e26854ab2f1", "is_commit_specific": true, "type": "overwrite", "overwrite_rate": { "rate_type":"flat", "price": 75 } }, { "starting_at": "2024-10-01T00:00:00.000Z", "product_id": "1e0f9c54-56c9-4587-b0ad-a94b53fe623a", "is_commit_specific": true, "type": "overwrite", "overwrite_rate": { "rate_type":"flat", "price": 88.9 } } ] }' ``` ## Encoding commit rates on the rate card​ Some clients have a business model with consistent *commit rates* offered to all customers who sign up for a commitment. Metronome makes it easy to encode these commit rates on the rate card, so you don’t need to use commit-specific overrides for every customer who makes a commitment. In addition, Metronome offers the flexibility to further discount the commit rate to account for per-customer negotiation. ### 1. Set up commit rates on the rate card.​ First, define the commit rate on the rate card. You can do this using the [Metronome app](https://app.metronome.com/) or the [Metronome API](/api-reference/rate-cards/add-a-rate). Note: * Commit rates are only supported for usage products. * Commit rates must be added with a list rate. There is no way to just change a commit rate; you must add a list rate with it. * List and commit rate must be in the same pricing unit. * The commit rate (and the list rate) can be tiered. The tier quantity is not reset between using the commit rate and the list rate. Commit rate on a rate card ### 2. Create the commit.​ Next, create the commit on a contract. Specify that the commit should use the commit rate. Only specify that a commit or credit uses the commit rate if you’ve added distinct commit rates to the rate card. **FALLBACK BEHAVIOR** If you add to a customer or contract a commit or credit that uses a commit rate and there is no commit rate for a given product, Metronome applies the list rate as well as any overrides that target list rate. Any overrides that target commit rate are ignored. ### 3. (Optional) Offer discounts on the commit rate.​ Metronome supports discounting the default commit rate by adding a commit-specific override on the contract. To do so: * Specify that the type of override is `commit-specific`. * Specify that the target of the override is `COMMIT_RATE`. * Add specific `commit ids`. If `commit_ids` are not specified, the override applies whenever a prepaid or postpaid commit is used. You should only specify overrides with the rate target `COMMIT_RATE` if you’ve added distinct commit rates to the rate card. Otherwise Metronome applies the fallback behavior (mentioned above). ### Commit and on-demand rates with no discounts example​ As an example, consider a client with list rates and commit rates consistent across all customers or a subset of their customers. First, specify the commit rates on the rate card: ```bash theme={null} curl https://api.metronome.com/v1/contract-pricing/rate-cards/addRate \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "rate_card_id": "d7abd0cd-4ae9-4db7-8676-e986a4ebd8dc", "product_id": "13117714-3f05-48e5-a6e9-a66093f13b4d", "starting_at": "2024-10-01T00:00:00.000Z", "entitled": true, "rate_type": "FLAT", "price": 1000, "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "commit_rate": { "rate_type":"FLAT", "price":800 } }' ``` Next, when creating a commit on a customer or contract, specify that the commit should use `commit_rate`: ```bash theme={null} curl https://api.metronome.com/v1/contracts/customerCommits/create \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "13117714-3f05-48e5-a6e9-a66093f13b4d", "type": "prepaid", "name": "Commitment - using commit rate", "priority": 100, "product_id": "f14d6729-6a44-4b13-9908-9387f1918790", "rate_type":"commit_rate", "access_schedule": { "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "schedule_items": [ { "amount": 10000, "starting_at": "2024-10-01T00:00:00.000Z", "ending_before": "2024-11-01T00:00:00.000Z" } ] }, "invoice_schedule": { "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "schedule_items": [ { "unit_price": 8000, "quantity": 1, "timestamp": "2024-10-01T00:00:00.000Z" } ] } }' ``` Now, when consuming the commit, commit rates on the rate card are used. **TIP** Note that it's possible to encode specific rates when burning down commits for a customer by only using commit-specific overrides. But by using commit rates on the rate card, you can set the rates up once rather than adding commit-specific overrides to each customer’s contract. ### Negotiated commit and on-demand rates example As another example, consider a client with list rates and commit rates consistent across all customers (see the table below). A single customer can negotiate both the rate when using a specific commit (off of commit rate) and their rate when not consuming a commit (off of list rate). | List rate shared across all customers | Commit rate shared across all customers | Negotiated commit rate for commit A for customer A | Negotiated on-demand rate for customer A | | | ------------------------------------- | --------------------------------------- | -------------------------------------------------- | ---------------------------------------- | ---- | | Audio Input tokens (1M) | \$10 | \$8 | \$7.2 | \$8 | | Audio output tokens (1M) | \$20 | \$19 | \$17.1 | \$16 | To implement this discount pattern: 1. Specify the commit rates on the rate card (\$8 and \$19). 2. When creating commit A on the contract, specify that commit A should use `commit_rate`. 3. Add two overrides to the contract: * Override 1: commit-specific override, against `commit_rate`, limited to commit A, 0.9 multiplier. * Override 2: override against list rate, 0.8 multiplier. This example API request edits a contract, including the prepaid commit: ```bash theme={null} curl https://api.staging.metronome.com/v2/contracts/edit \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "bc20325a-80a0-468e-868f-a2f28b972af8", "contract_id": "82a884c5-5e3e-47ae-b056-63b6f3a84674", "add_commits": [ { "temporary_id": "prepaid_commit_A", "type": "prepaid", "priority": 1, "rate_type": "commit_rate", "name": "Prepaid Commit A", "product_id": "f14d6729-6a44-4b13-9908-9387f1918790", "access_schedule": { "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "schedule_items": [ { "amount": 1000000, "starting_at": "2024-10-01T00:00:00.000Z", "ending_before": "2025-10-01T00:00:00.000Z" } ] }, "invoice_schedule": { "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "schedule_items": [ { "unit_price": 1000000, "quantity": 1, "timestamp": "2024-10-01T00:00:00.000Z" } ] } } ], "add_overrides": [ { "starting_at": "2024-10-01T00:00:00.000Z", "multiplier": 0.9, "is_commit_specific": true, "rate_target": "commit_rate", "type": "multiplier", "override_specifiers": [ { "commit_ids": [ "prepaid_commit_A" ] } ] }, { "starting_at": "2024-10-01T00:00:00.000Z", "multiplier": 0.8, "rate_target": "list_rate", "type": "multiplier", "override_specifiers": [ { "product_tags": [ "audio" ] } ] } ] }' ``` # Guarantee zero overages Source: https://docs.metronome.com/guides/pricing-packaging/apply-credits-and-commits/guarantee-zero-overages Some customers must never be billed for usage beyond their committed balance—free trial accounts, fraud-sensitive segments, or customers on strict internal budgets. Guarantee zero overages in Metronome by setting list rates to 0 USD and encoding the real prices either as a commit rate on the rate card or as a commit-specific override on the contract. Usage burns down the commit at the real prices while balance exists, and falls back to 0 USD after the commit is exhausted. **Only use this pattern when customers must never be charged for overages.** If you want to allow overages but need controls around them, Metronome offers two complementary mechanisms instead: * **[Prepaid balance thresholds](/guides/customers-billing/optimize-customer-experience/prepaid-balance-thresholds)** auto-recharge a customer's prepaid commit balance when it drops to a `threshold_amount`, topping it back up to a `recharge_to_amount`. Useful when you want continuous service with automatic top-ups. * **[Spend thresholds](/guides/customers-billing/optimize-customer-experience/set-customer-spend-control)** cap how much a customer can accrue before a payment is triggered—useful for limiting fraud exposure in PLG workflows. The pattern below is the right choice only when there is no tolerance for charging customers overages. ## When to use this pattern This approach is useful when: * **Free trials** must hard-cap at the granted amount with no possibility of a bill. * **Fraud-sensitive accounts** could otherwise rack up runaway usage before fraud signals fire. * **Strict-budget customers** require a contractual guarantee that you never invoice them for overages, even if your application's gating fails. ## How it works Two pieces work together: 1. **List rate of 0 USD** on the rate card. This is the fallback price after any commit is exhausted, so any leaked usage is billed at 0 USD. 2. **A real per-unit price that only applies while a commit is being drawn down.** You can encode this real price in one of two ways depending on whether prices are uniform across customers or set per customer. Because both mechanisms only apply while usage is consuming a commit, pricing reverts to the 0 USD list rate the moment the commit hits zero. From that point forward, the line item resolves to 0 USD and the customer is never invoiced for overages. ## Choose your implementation | | Option A: Commit rate on the rate card | Option B: Commit-specific override on the contract | | ------------------------ | ------------------------------------------------------------------------ | -------------------------------------------------- | | **Where prices live** | On the rate card, alongside the 0 USD list rate | On each customer's contract | | **Best for** | Uniform pricing across all (or most) customers on the rate card | Per-customer customization of commit prices | | **Setup cost** | Configure once on the rate card | Add an override on every contract | | **Customer inheritance** | All customers using the rate card automatically inherit the commit price | Each contract specifies its own commit price | You can combine the two: set a default commit rate on the rate card for most customers, and use commit-specific overrides on contracts that need a different price. Overrides on the contract take precedence. ## Option A: Commit rate on the rate card Use this when the real price is consistent across all (or most) customers on the rate card. You set the list rate to 0 USD and the real price as a `commit_rate` on the same rate card entry. Customers inherit both automatically—no per-contract override required. ### 1. Add the product to the rate card with `price: 0` and a `commit_rate` ```bash theme={null} curl https://api.metronome.com/v1/contract-pricing/rate-cards/addRate \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "rate_card_id": "d7abd0cd-4ae9-4db7-8676-e986a4ebd8dc", "product_id": "13117714-3f05-48e5-a6e9-a66093f13b4d", "starting_at": "2024-10-01T00:00:00.000Z", "entitled": true, "rate_type": "FLAT", "price": 0, "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "commit_rate": { "rate_type": "FLAT", "price": 100 } }' ``` ### 2. Create the commit and tell it to use `commit_rate` When you create the commit on the contract, set `rate_type: commit_rate` so that drawdowns are priced against the rate card's commit rate. ```bash theme={null} curl https://api.metronome.com/v1/contracts/customerCommits/create \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "bc20325a-80a0-468e-868f-a2f28b972af8", "type": "prepaid", "name": "Trial credit", "priority": 100, "product_id": "f14d6729-6a44-4b13-9908-9387f1918790", "rate_type": "commit_rate", "access_schedule": { "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "schedule_items": [ { "amount": 10000, "starting_at": "2024-10-01T00:00:00.000Z", "ending_before": "2025-10-01T00:00:00.000Z" } ] }, "invoice_schedule": { "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "schedule_items": [ { "unit_price": 10000, "quantity": 1, "timestamp": "2024-10-01T00:00:00.000Z" } ] } }' ``` While the commit has balance, usage is priced at the rate card's `commit_rate` (100 USD/unit). After the commit is exhausted, usage falls back to the rate card's 0 USD list rate. ## Option B: Commit-specific override on the contract Use this when each customer needs different prices, or when you don't want to encode the real prices on the rate card. The list rate stays 0 USD on the rate card, and you add an `overwrite` override on each contract that only applies while the commit has balance. ### 1. Set the list rate to 0 USD on the rate card ```bash theme={null} curl https://api.metronome.com/v1/contract-pricing/rate-cards/addRate \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "rate_card_id": "d7abd0cd-4ae9-4db7-8676-e986a4ebd8dc", "product_id": "13117714-3f05-48e5-a6e9-a66093f13b4d", "starting_at": "2024-10-01T00:00:00.000Z", "entitled": true, "rate_type": "FLAT", "price": 0, "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2" }' ``` ### 2. On the contract, add a commit and a commit-specific override The override is scoped to the commit via `override_specifiers.commit_ids`, so it only applies while that commit has remaining balance. ```bash theme={null} curl https://api.metronome.com/v1/contracts/create \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "bc20325a-80a0-468e-868f-a2f28b972af8", "starting_at": "2024-10-01T00:00:00.000Z", "rate_card_id": "d7abd0cd-4ae9-4db7-8676-e986a4ebd8dc", "commits": [ { "temporary_id": "prepaid_commit_A", "type": "prepaid", "priority": 1, "name": "Trial credit", "product_id": "f14d6729-6a44-4b13-9908-9387f1918790", "access_schedule": { "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "schedule_items": [ { "amount": 10000, "starting_at": "2024-10-01T00:00:00.000Z", "ending_before": "2025-10-01T00:00:00.000Z" } ] }, "invoice_schedule": { "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "schedule_items": [ { "unit_price": 10000, "quantity": 1, "timestamp": "2024-10-01T00:00:00.000Z" } ] } } ], "overrides": [ { "starting_at": "2024-10-01T00:00:00.000Z", "is_commit_specific": true, "product_id": "13117714-3f05-48e5-a6e9-a66093f13b4d", "type": "overwrite", "overwrite_rate": { "rate_type": "flat", "price": 100 }, "override_specifiers": [ { "commit_ids": ["prepaid_commit_A"] } ] } ] }' ``` While the commit has balance, the override applies and usage is priced at 100 USD/unit. After the commit is exhausted, the override no longer applies and usage falls back to the rate card's 0 USD list rate. **App-side gating is still required** This pattern guarantees zero billing for any usage that leaks through, but it does not stop usage from being submitted. Gate access in your application using [balance thresholds](/guides/pricing-packaging/apply-credits-and-commits/alerts) or webhooks so customers can't continue consuming the product after their commit is exhausted. # Payment-gated commits Source: https://docs.metronome.com/guides/pricing-packaging/apply-credits-and-commits/manual-payment-gated-commits Organizations commonly implement a prepaid model for their PLG customers. Customers must pay for usage in advance of using the product and organizations gate access pending successful payment. This can be implemented in Metronome using payment-gated commits. When a payment-gated commit is created, Metronome facilitates the following: 1. Metronome immediately triggers a payment attempt based on the invoice amount of the commit. 2. If the payment succeeds, Metronome releases the commit and the customer is granted access to the associated balance. 3. If the payment fails, Metronome voids the resource and sends a webhook notification. 4. If further action is required (e.g. for 2F authentication), Metronome sends a webhook notification. **IMMEDIATELY** Metronome initiates payment with your configured billing provider and monitors for completion. In most success cases, payment is completed and credits are released within seconds, but actual timing depends on the payment provider, payment method, and potential authentication challenges. ## Before you begin * Ensure the customer has a default payment method configured in your payment provider (e.g., Stripe); otherwise, payments will fail and commits will not be created. * Capture and store customer address during your checkout flow. If address is invalid or missing, subsequent payments for the customer will fail. * **Map the commit's Metronome product to a Stripe product.** Payment-gated commits require that the Metronome product used on the commit has a corresponding Stripe Product ID mapped to it. Without this mapping, Stripe cannot generate the invoice line item and the payment attempt will fail. To configure this mapping, create a `stripe_product_id` custom field on the Metronome product entity, set its value to the corresponding Stripe Product ID, and add a Stripe integration mapping rule from `stripe_product_id` to `invoiceitem.price`. See [Assign line items to Stripe products](/integrations/invoice-integrations/stripe#create-optional-entity-mapping-rules) in the Stripe invoicing guide for step-by-step instructions. ## Add a payment-gated commit to an existing contract​ Payment gated commits can only be added to existing contracts. You can create a payment-gated commit by [editing the user's contract](/api-reference/contracts/edit-a-contract). Make sure the contract has a valid billing configuration. See below for an example API call: ```json theme={null} { "customer_id": "8cecbf69-960f-4f66-9575-edebb7d95e88", "contract_id": "d7abd0cd-4ae9-4db7-8676-e986a4ebd8dc", "add_commits": [ { "product_id": "d6be3bf4-1669-40c9-a8b1-388bb167ab16", "type": "prepaid", "invoice_schedule": { "schedule_items": [ { "timestamp": "2025-04-01T00:00:00.000Z", "amount": 2000 } ] }, "access_schedule": { "schedule_items": [ { "amount": 2000, "starting_at": "2025-04-01T00:00:00.000Z", "ending_before": "2026-04-01T00:00:00.000Z" } ] }, "payment_gate_config": { "payment_gate_type": "STRIPE", "tax_type": "STRIPE" }, "priority": 100 } ] } ``` ## Manage notifications​ Two types of webhook notifications are emitted when creating a payment-gated commit: * `payment_gate.payment_status` after payment has been attempted. The status of that payment, `paid` or `failed` , is denoted in the `payment_status` field. * `payment_gate.payment_pending_action_required` if intervention is required to process payment. See our full set of our webhook notifications [here](/guides/platform-configuration/setup-webhooks#payment-gating-notifications). ## Handle failed payments​ If payment fails, the associated invoice in Metronome and Stripe is voided and no commit is created. To retry the payment, send a new API request with the relevant commit information. **NO AUTOMATIC RETRIES** Metronome does not automatically retry failed payments (as any automatic retries would likely fail, too). # Understand prioritization rules Source: https://docs.metronome.com/guides/pricing-packaging/apply-credits-and-commits/prioritization-rules To ensure consistent and predictable billing, Metronome follows a structured set of prioritization rules to determine burn down of commits and credits. The page explains the complete burn down sequence for different types of financial instruments, as well as how line items on invoices are prioritized. ## Prioritizing between commits and credits​ If a customer has multiple active credits or commits that can apply against the same usage, Metronome uses a series of rules to determine which credit or commit to consume first. ### Overall burn-down order Before applying the rules within each type, Metronome burns down commits in this sequence: 1. **Rollover commits** (post-paid commits rollover before prepaid commits/credits) 2. **Prepaid commits and credits** 3. **Post-paid commits** **Commit type always takes precedence over priority.** The `priority` field only controls ordering *within* the same commit type—it cannot cause a post-paid commit to burn down before a prepaid commit, or vice versa. ### Rollover commits and credits​ 1. If there are multiple rollover commits or credits, burn down is based on **commit or credit type.** Post-paid rollover commits burn down before prepaid commits and credits. 2. If there are multiple rollover commits or credits with the same type, burn down is based on **priority.** 3. If there are multiple rollover commits or credits with the same type and priority, burn down is based on **product applicability.** Commits with the fewest applicable products first, most applicable products last. 4. If there are multiple rollover commits or credits with the same type, priority, and product applicability, burn down is based on **usage applicability** —the number of group value specifiers a commit has. Commits with the fewest applicable usage get consumed first, and the most applicable usage get consumed last. 5. If there are multiple rollover commits or credits with the same type, priority, and product and usage applicability, burn down is based on `ending_before`. The earlier `ending_before` gets burned down first. **INFO** Group value specifiers are specifiers with only `presentation_group_value` or `pricing_group_value` defined. Commits with `applicable_product_ids` or `applicable_product_tags` have no usage applicability since they lack group value specifiers. ### Prepaid commits and credits​ Prepaid commits and credits always burn down before post-paid commits, regardless of priority values. 1. If there are multiple prepaid commits and credits, burn down is based on **priority.** 2. If there are multiple other prepaid commits or credits with the same priority, burn down is based on **commit cost basis**. \$0 cost basis burns down first, then paid. 3. If there are multiple other prepaid commits or credits with the same priority and cost basis, burn down is based on **product applicability** . The fewest applicable products first, most applicable products last. 4. If there are multiple other prepaid commits or credits with the same commit type, priority, and product applicability, burn down is based on **usage applicability** —the number of group value specifiers a commit has. Commits with the fewest applicable usage get consumed first, and the most applicable usage get consumed last. 5. If there are multiple other prepaid commits or credits with the same priority, cost basis, and product and usage applicability, burn down is based on `ending_before`. The earlier `ending_before` burns down first. 6. If there are multiple prepaid commits or credits with the same priority, cost basis, product and usage applicability, and `ending_before`, burn down is based on `starting_on`. The earlier `starting_on` burns down first. 7. If there are multiple prepaid commits or credits with the same priority, cost basis, product and usage applicability, `ending_before`, and `starting_on`, burn down is based on the **number of contracts a commit applies to**. The commit with the least number of applicable contracts burns down first. ### Post-paid commits​ Post-paid commits always burn down after prepaid commits and credits, regardless of priority values. Within post-paid commits, burn down follows the same order logic as prepaid commits: priority, cost basis, product applicability, `ending_before`, `starting_on`, then number of applicable contracts. This example API request creates the contract with prepaid commits. The contract's prepaid commits burn down in this order: 1. Prepaid Commit A since it has the highest priority. 2. Prepaid Commit B since it has a zero-cost basis for commits with the same priority. 3. Prepaid Commit C since it has the lowest usage applicability for commits with the same priority, cost basis, and product applicability. 4. Prepaid Commit D since it has the earliest `ending_before` for commits with the same priority, cost basis, and product and usage applicability. 5. Prepaid Commit E since it has the next earliest `ending_before` for commits with the same priority, cost basis, and product and usage applicability. 6. Prepaid Commit F since it's applicable to all usage and products for commits with the same priority. ```bash theme={null} curl https://api.staging.metronome.com/v1/contracts/create \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "bc20325a-80a0-468e-868f-a2f28b972af8", "starting_at": "2024-10-01T00:00:00.000Z", "rate_card_id": "d7abd0cd-4ae9-4db7-8676-e986a4ebd8dc", "commits": [ { "type": "prepaid", "priority": 50, "name": "Prepaid Commit A", "product_id": "f14d6729-6a44-4b13-9908-9387f1918790", "access_schedule": { "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "schedule_items": [ { "amount": 1000000, "starting_at": "2024-10-01T00:00:00.000Z", "ending_before": "2025-10-01T00:00:00.000Z" } ] }, "invoice_schedule": { "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "schedule_items": [ { "unit_price": 1000000, "quantity": 1, "timestamp": "2024-10-01T00:00:00.000Z" } ] } }, { "type": "prepaid", "priority": 100, "name": "Prepaid Commit B", "product_id": "f14d6729-6a44-4b13-9908-9387f1918790", "access_schedule": { "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "schedule_items": [ { "amount": 1000000, "starting_at": "2024-10-01T00:00:00.000Z", "ending_before": "2025-10-01T00:00:00.000Z" } ] } }, { "type": "prepaid", "priority": 100, "name": "Prepaid Commit C", "product_id": "f14d6729-6a44-4b13-9908-9387f1918790", "access_schedule": { "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "schedule_items": [ { "amount": 1000000, "starting_at": "2024-10-01T00:00:00.000Z", "ending_before": "2025-10-01T00:00:00.000Z" } ] }, "invoice_schedule": { "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "schedule_items": [ { "unit_price": 1000000, "quantity": 1, "timestamp": "2024-10-01T00:00:00.000Z" } ] }, "applicable_product_ids": [ "dbb46a31-3437-4df2-ade1-46a2641623ab" ] }, { "type": "prepaid", "priority": 100, "name": "Prepaid Commit D", "product_id": "f14d6729-6a44-4b13-9908-9387f1918790", "access_schedule": { "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "schedule_items": [ { "amount": 1000000, "starting_at": "2024-10-01T00:00:00.000Z", "ending_before": "2025-10-01T00:00:00.000Z" } ] }, "invoice_schedule": { "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "schedule_items": [ { "unit_price": 1000000, "quantity": 1, "timestamp": "2024-10-01T00:00:00.000Z" } ] }, "specifiers": [ { "product_id": "dbb46a31-3437-4df2-ade1-46a2641623ab", "pricing_group_values": { "region": "us-east-1" } }, { "pricing_group_values": { "region": "us-west-1" } } ] }, { "type": "prepaid", "priority": 100, "name": "Prepaid Commit E", "product_id": "f14d6729-6a44-4b13-9908-9387f1918790", "access_schedule": { "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "schedule_items": [ { "amount": 1000000, "starting_at": "2024-10-01T00:00:00.000Z", "ending_before": "2026-10-01T00:00:00.000Z" } ] }, "invoice_schedule": { "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "schedule_items": [ { "unit_price": 1000000, "quantity": 1, "timestamp": "2024-10-01T00:00:00.000Z" } ] }, "specifiers": [ { "product_id": "dbb46a31-3437-4df2-ade1-46a2641623ab", "pricing_group_values": { "region": "us-east-1" } }, { "pricing_group_values": { "region": "us-west-1" } } ] }, { "type": "prepaid", "priority": 100, "name": "Prepaid Commit F", "product_id": "f14d6729-6a44-4b13-9908-9387f1918790", "access_schedule": { "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "schedule_items": [ { "amount": 1000000, "starting_at": "2024-10-01T00:00:00.000Z", "ending_before": "2025-10-01T00:00:00.000Z" } ] }, "invoice_schedule": { "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "schedule_items": [ { "unit_price": 1000000, "quantity": 1, "timestamp": "2024-10-01T00:00:00.000Z" } ] } } ] }' ``` ## Line item prioritization​ If there are multiple line items on the invoice eligible for commit or credit application, Metronome uses rules to determine which line item to apply commit or credit to first: 1. Commits or credits are applied against usage products first, then subscription products, then composite products. 2. If there are multiple products of the same type, Metronome uses the start date of the line item, applied against earlier start dates first. 3. If there are multiple products of the same type with the same start date, Metronome uses the unit price of the line item, applied against line items with higher unit prices first. 4. If there are multiple products of the same type with the same type, start date and unit price, Metronome uses the line item name, applied alphabetically from A to Z. For example, imagine a usage invoice with two usage products: Data Storage with a unit price of \$1, and Data Reads with a unit price of \$2.6 dollars. The line items have the same effective dates spanning the entire billing period. Any commit or credit first gets applied against Data Reads, as it has the higher unit price. # Target usage with credits and commits Source: https://docs.metronome.com/guides/pricing-packaging/apply-credits-and-commits/target-credit-and-commits You can grant credits and create commitments that are only applicable to a subset of a customer’s usage. Choose to target the usage of specific products, product families, pricing dimensions, and even dimensions not used for pricing. This gives you the flexibility to negotiate enterprise commitments based on any dimension and to try out different pricing incentives. Metronome provides two options to target credits and commits: * Target with `applicable_product_ids` and `applicable_product_tags` if you want to filter only on product ID or product family, and don’t require complex AND/OR logic * Target with `specifiers` if you want to filter based on pricing group values or presentation group values, or require complex AND/OR logic ## Target with `applicable_product_ids` and `applicable_product_tags`​ For simple use cases that don't require complex AND/OR logic, use the `applicable_product_ids` and `applicable_product_tags` fields to target your credit or commit. Usage that matches *any* of the listed product IDs and product tags is eligible to consume the credit or commit. ## Target with `specifiers`​ Specifiers provide the flexibility to power more complex use cases involving pricing group values, presentation group values, or advanced boolean logic. The `specifiers` field takes in an array of objects, where each object is called a specifier. Within each specifier all fields are ANDed together. If the conditions of any specifier in the array are met, the line item is eligible to consume the commit or credit. This is logic identical to [override\_specifiers](/guides/pricing-packaging/make-pricing-changes/edit-or-override-a-contract#target-overrides), which you can use to grant discounts based on complex logic. Note that if you use pricing group values and/or presentation group values in a specifier, only usage of products with the corresponding pricing and presentation group values will match that specifier. For example, if you create a credit that applies when pricing group value `region` = `us-east-1`, products that do not have the pricing group key `region` will never draw down the credit. Subscriptions and composite products never have pricing or presentation group values, so would not draw down the commit. ### Example: Commit applies to only two `regions` (pricing group value)​ Consider a scenario where you’ve negotiated an enterprise commitment with a large customer. They only plan to use your product in two specific `regions`, and you’ve negotiated that the commitment only covers usage in those `regions`. `region` is a pricing group key for your products. Your products are available in many regions, and you use [dimensional pricing](/guides/get-started/core-concepts/create-manage-rate-cards#how-dimensional-pricing-works%E2%80%8B) to price a single product differently by region. This example API call creates a contract that specifies the `pricing_group_values` for the `us-east-1` and `us-east-2` regions. ```bash theme={null} curl https://api.metronome.com/v1/contracts/create \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "47e8f505-3c08-4c9d-8323-14d36c21658e", "contract_id": "cf4b3e2d-d697-4c4b-869b-5db2dbb224f5", "starting_at": "2025-06-01T00:00:00.000Z", "commits": [ { "type": "PREPAID", "name": "Commit - us-east-1 and us-west-1 only", "product_id": "ffa5d53f-0b84-4d8d-bdb4-d21e7e104aa5", "access_schedule": { "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "schedule_items": [ { "amount": 50000, "starting_at": "2025-06-01T00:00:00.000Z", "ending_before": "2026-06-01T00:00:00.000Z" } ] }, "invoice_schedule": { "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "schedule_items": [ { "amount": 50000, "timestamp": "2025-06-01T00:00:00.000Z" } ] }, "specifiers": [ { "pricing_group_values": { "region":"us-east-1" } }, { "pricing_group_values": { "region":"us-west-1" } } ] } ] }' ``` ### Example: Credit applies to only one `user_id` (presentation group value)​ Consider a scenario where you want to grant a credit that's only usable for a specific `user_id` within an organization. You don’t price differently based on `user_id`, but you want to grant this specific user a credit in return for taking part in user research. `user_id` is a presentation group key across your products. This example API call edits a contract to add credits by specifying the `presentation_group_values` for a specific `user_id`: ```bash theme={null} curl https://api.metronome.com/v2/contracts/edit \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "47e8f505-3c08-4c9d-8323-14d36c21658e", "contract_id": "cf4b3e2d-d697-4c4b-869b-5db2dbb224f5", "add_credits": [ { "type": "PREPAID", "name": "Credit - user_123 only only", "product_id": "ffa5d53f-0b84-4d8d-bdb4-d21e7e104aa5", "access_schedule": { "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "schedule_items": [ { "amount": 500, "starting_at": "2025-06-01T00:00:00.000Z", "ending_before": "2026-06-01T00:00:00.000Z" } ] }, "specifiers": [ { "presentation_group_values": { "user_id": "user_123" } } ] } ] }' ``` ### Example: Commit applies to products with both product tags​ Product tags make it very straightforward to launch new products. Consider a scenario where, as part of negotiating an enterprise contract, you’ve agreed that a postpaid commitment applies to all products in the *Audio* model family that are also *Basic* models (a non-premium offering). By using product tags, any new products you launch that are *Basic* , *Audio* models automatically draw down from the postpaid commitment, with no additional work required. *Basic* and *Audio* models are both product tags. This example API call edits a contract to add a commit, specifying the `product_tags` `Audio` and `Basic`: ```bash theme={null} curl https://api.metronome.com/v2/contracts/edit \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "47e8f505-3c08-4c9d-8323-14d36c21658e", "contract_id": "cf4b3e2d-d697-4c4b-869b-5db2dbb224f5", "starting_at": "2025-06-01T00:00:00.000Z", "add_commits": [ { "type": "PREPAID", "name": "Commit - basic audio models", "product_id": "ffa5d53f-0b84-4d8d-bdb4-d21e7e104aa5", "access_schedule": { "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "schedule_items": [ { "amount": 50000, "starting_at": "2025-06-01T00:00:00.000Z", "ending_before": "2026-06-01T00:00:00.000Z" } ] }, "invoice_schedule": { "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "schedule_items": [ { "amount": 50000, "timestamp": "2025-06-01T00:00:00.000Z" } ] }, "specifiers": [ { "product_tags": [ "Audio", "Basic" ] } ] } ] }' ``` # Create a free trial Source: https://docs.metronome.com/guides/pricing-packaging/billing-model-guides/create-a-trial This use case explores how Metronome's billing platform enables you to effectively manage free trials by tracking usage metrics and duration. Free trials are a cornerstone of self-service and product-led growth strategies, allowing potential customers to experience the value of a product before committing to a purchase. However, configuring free trials in a usage-based billing model presents unique challenges. While traditional subscription models often rely on simple time-limited trials, usage-based services must carefully balance customer experience with potential costs. The definition of "free" becomes complex when users can potentially accumulate significant charges during their trial period. To solve this, Metronome can help your business offer compelling trial experiences while safeguarding margins and controlling COGS. This use case walks through two free trial scenarios in Metronome: * Create a capped free trial on a limited set of products using time-bound credits, alerts, and entitlement overrides. * Create an uncapped free trial using time-bound contract overrides. ## Create a credit-based free trial​ A credit-based free trial involves allocating a specific amount of usage credits to new users, allowing them to explore your product within predefined limits. Many Metronome customers opt for this approach as a strategic way to balance generous product exposure with controlled risk. This method allows you to offer a substantial trial experience while preventing runaway usage that could impact your bottom line. In this example, learn how to create a trial for a customer with the following conditions: * The customer has free access to the platform for up to one week after sign-up. * The customer trial ends if they reach up to \$100 of usage in the platform. * The customer trial only includes a certain set of products. For example, the user is allowed to access the *Language models* functionality, but not *Fine tuning* or *Image generation* features. * When the trial ends (due to time or usage) you receive a real-time notification from Metronome. This allows you to manage a customer's state based on their usage in Metronome—for instance, send them an email that their trial has ended, or disable their account until they purchase further usage. ### Pre-requisites​ Before getting started, make sure you have a [rate card](/guides/get-started/core-concepts/create-manage-rate-cards) and an example [customer](/guides/customers-billing/manage-customers/provision-a-customer) to sign up for the trial. Our example uses a newly created customer, **AcmeCorp** , with a rate card based on some example **GenAI List Prices**. ### Configure a contract with free trial credits​ To create and configure a contract with free trial credits: 1. On the **Customers** page, click on your customer. 2. Click New contract or plan -> **New contract...** 3. Configure the contract for your customer. * Add a contract name. * Select the rate card. * Set the contract start and end dates. * Set the contract billing frequency. Configure contract 4. Click **Add a credit** to configure the trial terms. * Select an existing **Credit product** or create a new fixed product called **Trial credits**. The name of the fixed product selected is the name displayed to your customer. * Add an optional description. This is not displayed to your customer. Think of this as useful metadata for users of Metronome, like you. * Leave **Applicable products** and **Applicable tags** blank. This configures the credits to track all usage for your customer. * Under **Access schedule** , set these terms: * Set **Starting at** to match your contract start date. * Set **Ending before** to be one week after your **Starting at** date. This way, if a customer doesn't use all of their free credits by the end of the trial period, the credits expire and customers pay for subsequent usage. * Set the **Amount** to be \$100. * If you've included any other commits or credits in your contract, ensure that the **Priority** is set lower than the others. > In general, Metronome recommends using whole numbers for priority. For free trials, set a low number like 1 so they clearly take precedence over any other grants. Learn more on how priority is used to [orchestrate burn-down](/guides/pricing-packaging/apply-credits-and-commits/prioritization-rules). * When complete, click **Add**. Set credit terms 5. (Optional) To help gate access to certain features while your customer is in the trial phase, set an override on the entitlement state for the particular rate. You can then read from this override to restrict access inside of your product. * Click **+ Add an override** * Select the product or product tags that you want to disable. In this example, you disable any products with the tags *Fine tuning* and *Images modeled*. * Set **Starting at** to match your contract start date. * Set **Ending before** to be one week after your **Starting at** date. * Set **Entitlement** to **Disable** . * When complete, click **Create**. Add an override 6. Save your changes to create and submit the contract. If you prefer to use the API, this example payload shows how to create the credit-based free trial contract from the example with one request: ```bash theme={null} curl https://api.metronome.com/v1/contracts/create \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "13117714-3f05-48e5-a6e9-a66093f13b4d", "rate_card_id": "d7abd0cd-4ae9-4db7-8676-e986a4ebd8dc", "starting_at": "2024-09-01T00:00:00.000Z", "ending_before": "2025-09-01T00:00:00.000Z", "name": "AcmeCorp List Prices", "credits": [ { "name": "Trial credits", "product_id": "609e4cf2-6ea2-4b07-a46c-6596f041b69e", "access_schedule": { "schedule_items": [ { "amount": 10000, "starting_at": "2024-09-01T00:00:00.000Z", "ending_before": "2024-09-08T00:00:00.000Z" } ] }, "description": "Free usage as part of trial", "priority": 1 } ], "overrides": [ { "starting_at": "2024-09-01T00:00:00.000Z", "ending_before": "2024-09-08T00:00:00.000Z", "entitled": false, "applicable_product_tags": [ "Fine tuning", "Images modeled" ] } ] }' ``` After you submit the contract, you can un-gate your customer’s access to your product and observe how they use it. ### Track customer usage​ To track customer usage of your product, use Metronome APIs to create a [customer usage dashboard](/guides/customers-billing/optimize-customer-experience/customer-dashboards-and-reporting). This provides visibility into consumption in real-time and can be exposed directly to your customer. Once the customer spends the full \$100 of allotted credits, or once the trial week has passed, any subsequent usage is rated and charged in arrears based on your list pricing and billing frequency. ### Create an alert to signal the end of the trial period​ Your system likely needs to know in real-time once a customer’s trial period ends. You can configure alerts in Metronome to notify you when the customer’s credit balance has reached 0, either due to usage or credit expiration. You can use this notification as a signal to disable a customer’s access to your platform, or to re-enable the full suite of features now that their trial has ended. To configure alerting: 1. Define an alert to notify you upon expiration or full usage of the trial credits. * Go to **Alerts** in the Metronome [app](https://app.metronome.com/alerts) and click **+ Create alert**. * Name your alert **Trial Usage - AcmeCorp**. * Select the alert type **Contract credit balance**. * Set alert threshold to **reaches \$0 USD**. * In **Step 3: Select customers** , specify that the alert should only apply to customer **AcmeCorp**. * Ensure that you have a [webhook endpoint](/guides/platform-configuration/setup-webhooks) configured to receive the notification from Metronome. * When finished, click **Save**. Create an alert 1. Receive the webhook from Metronome when the credit balance reaches 0. * Ensure that you have a webhook destination set up in Metronome. * When a customer's trial expires or their usage cap is reached, you receive a request from Metronome at the webhook destination with this body: ```json theme={null} { "id": "02d8d086-38cb-468e-ab7b-927d16cff708", "properties": { "customer_id": "13117714-3f05-48e5-a6e9-a66093f13b4d", "alert_id": "de83d270-f518-4cee-bb15-12f453b303df", "threshold": 0, "alert_name": "Trial Usage - AcmeCorp", "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "remaining_balance": 0, "triggered_by": "usage" }, "type": "alerts.low_remaining_contract_credit_and_commit_balance_reached" } ``` * Upon receiving this request, take action on the customer within your product. Either send them an email or cut off their access until they upgrade their subscription. ## Create an uncapped free trial​ While credit-based trials offer precise control over usage limits, you might prefer to offer uncapped access for a fixed duration to showcase your product's full potential. This approach is particularly effective for products with high perceived value or complex features that require more exploration time. Metronome's billing system also accommodates this strategy, allowing you to set up time-limited trials without usage restrictions while still maintaining visibility into consumption patterns. In this example, learn how to create a trial for a customer with the following conditions: * The customer has free access to the platform for up to one week after sign-up. * The customer can use as much of the product as they want with no capped usage. * The customer trial only includes a certain set of products. For example, the user is allowed to use the *Language models* functionality, but not *Fine tuning* or *Image generation* features. * When the trial ends, the customer is automatically transitioned into a paid user. ### Configure a contract with time-bound price overrides​ To create and configure a contract with time-bound price overrides: 1. Follow steps 1 and 2 described in the section **Configure a contract with free trial credits** to create a contract for your customer. 2. Click **+ Add an override** to create your free trial with a time-bound price override. * Select the relevant products or product tags that you want to offer for the free trial. In this example, apply the override to all products with the tag *Language models*. * Set **Starting at** to match your contract start date. * Set **Ending before** to be one week after your **Starting at** date. * Set **Adjustment type** to be **Multiplier** with a value of 0. * When finished, click **Create**. Configure a time-bound override 3. (Optional) To restrict access to certain products during the trial period, follow the entitlement override steps from step 5 in the section **Configure contract with free trial credits** . 4. Save your changes to create the contract. If you prefer to use the API, this example payload shows how to create the time-bound price override contract from the example with one request. ```bash theme={null} curl https://api.metronome.com/v1/contracts/create \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "13117714-3f05-48e5-a6e9-a66093f13b4d", "rate_card_id": "d7abd0cd-4ae9-4db7-8676-e986a4ebd8dc", "starting_at": "2024-09-01T00:00:00.000Z", "ending_before": "2025-09-01T00:00:00.000Z", "name": "AcmeCorp List Prices", "overrides": [ { "starting_at": "2024-09-01T00:00:00.000Z", "ending_before": "2024-09-08T00:00:00.000Z", "type": "multiplier", "multiplier": 0, "applicable_product_tags": [ "Language models" ] }, { "starting_at": "2024-09-01T00:00:00.000Z", "ending_before": "2024-09-08T00:00:00.000Z", "entitled": false, "applicable_product_tags": [ "Fine tuning", "Images modeled" ] } ] }' ``` At this point, the customer can begin using the platform as part of the free trial. You have visibility into their usage during the trial period. Once the trial completes, subsequent usage automatically charges in arrears at your list prices. # Launch an enterprise commit model Source: https://docs.metronome.com/guides/pricing-packaging/billing-model-guides/enterprise-commit This guide describes how to launch an enterprise commit model using Metronome, including: * Best practices for provisioning enterprise contracts for customers * How to execute against an SLG motion from initial provisioning through contract upsell, contract renewal, and financial reporting As companies begin to sell upmarket to enterprise customers, business models tend to get more complex. These customers have different expectations than individual consumers due to their comparatively high volume of usage. As a result, enterprise customers tend to negotiate longer term contracts in return for discounts and premium products. Often times, these contracts are based on a commitment by the enterprise to spend a certain amount. The Metronome data model provides first-class support for enterprise deal requirements like prepaid and postpaid commitments, negotiated discounts, one-time charges, contract renewals, and more. ## Use case​ This guide walks through an example using an infrastructure SaaS company, InfraX. InfraX sells storage and analysis products and is developing a sales-led growth (SLG) commit-based model. Your sales team at InfraX just closed its first enterprise deal with these terms: * The customer commits to spending \$500,000 over a three-year contract. * Usage is expected to ramp up as adoption at the customer organization increases, so they commit to a three-year schedule (allotment of usage): * Year 1: \$50,000 * Year 2: \$200,000 * Year 3: \$250,000 * They agree to pay for this commit across two installations: * Year 1: \$250,000 * Year 3: \$250,000 * In exchange for this prepaid commitment, the customer receives a 10% discount on all `storage` products in year 1 and a 20% discount thereafter. * If the customer completes an on-time renewal, they can roll over up to 25% of the original balance from their prepaid commitment. This was an important clause for the customer who was unsure whether they were agreeing to too large of a commitment. * The customer has purchased \$5,000 in professional support to help triage technical issues, which is paid in month 3 of the contract. Model these terms in Metronome after you design the Metronome building blocks for the enterprise. ## Metronome building blocks​ Even in enterprise sales, where customization is the norm, the basics of your business model remain the same. This is why Metronome [products](/guides/get-started/core-concepts/create-products-contracts) and [rate cards](/guides/get-started/core-concepts/create-manage-rate-cards) are common across all customers. Streamline the provisioning of contracts by setting up products and rate cards with enterprise commit models in mind. Enterprise commit model Follow these best practices to design your products and rate cards for enterprise. ### Use product tags to simplify discounts​ In an enterprise commit model, your customer typically agrees to commit to a certain amount of spend and, in return, you offer them discounted rates. Metronome [contracts](/guides/customers-billing/manage-customers/provision-a-customer) support rate overrides, which modify the default rate from a rate card to account for something like a discount. These overrides can target individual products or all products with one or more tags. These tags represent some grouping of products priced, discounted, or packaged similarly. You can change a product's tag at any time with the API or the [Metronome app](https://app.metronome.com/), but if you know in advance that you tend to discount certain products together, you'll save time by organizing products with tags up front. By doing this, you remove the need to store the `product.id` of each product that might be discounted as part of an enterprise deal. For a typical infrastructure SaaS company, this could mean storing a few tags as opposed to dozens of products. For this guide’s example, your company InfraX wants to give a discount on all products labeled with the `storage` tag. ### Make products for every kind of charge​ In Metronome, every charge on an invoice is associated with a [product](/guides/get-started/core-concepts/create-products-contracts). This includes one-time charges and upfront payments for prepaid commitments. Create these products with the `fixed` product type. Thinking through the different types of charges your sales team may offer leads to a smooth contract provisioning process. ### Design products with finance workflows in mind​ Downstream processes like tax calculation, data reconciliation for audits, or revenue recognition often need to know something about the charge. The Metronome product stores this information in a reusable way. For example, store the SKU ID from the relevant ERP system on the Product entity or the account ID from your CRM system on the customer entity as [custom fields](/developer-resources/custom-fields/). This can serve as a foreign key mapping between line items on the Metronome invoice and revenue buckets in the ERP system or other third-party entities. ## Implement the enterprise commit model​ Now that you’ve set things up following enterprise best practices, explore the end-to-end customer lifecycle from contract creation to contract upsell, renewal, and financial reporting. ### Provision customers with commitments​ In our example, InfraX’s sales team uses Salesforce CPQ to track the state of a given opportunity. Once the opportunity is closed in SFDC, encode the terms of the deal in Metronome. To encode deal terms in Metronome: 1. Create the customer in Metronome (if they don't already exist). 2. Provision the customer with a contract. ### Create the customer​ In Metronome, model the SFDC account as a Metronome customer and make the following POST request to `/customers` : ```bash theme={null} curl https://api.metronome.com/v1/customers \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "ingest_aliases": [ "internal_customer_id" ], "name": "Customer X", "customer_config": { "salesforce_account_id": "sfdc_account_01" } }' ``` This API call returns the created Metronome `customer.id`. Store this value, as you’ll need it to provision the customer with a contract. **TIP** The customer object can now serve as a join table between Metronome, SFDC, and your internal product. This can be useful for workflows like data reconciliation and revenue recognition. ### Provision a contract​ Now that the customer exists in Metronome, set the terms of their signed contract with an API call to `/contracts/create`. This example stores the relationship between the opportunity in SFDC and the contract in Metronome by setting the custom field on the contract object for `sfdc_opportunity_id`: ```bash theme={null} curl https://api.metronome.com/v1/contracts/create \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "c247f641-aa10-4167-bdbf-e1266810c4e4", "rate_card_alias": "my-rate-card", "starting_at": "2024-01-01T00:00:00Z", "ending_before": "2027-01-01T00:00:00Z", "commits": [ { "type": "prepaid", "product": "76e57c3a-064f-49ad-8740-2bff58f2f808", "access_schedule": { "schedule_items": [ { "amount": 5000000, "starting_at": "2024-01-01T00:00:00Z", "ending_before": "2025-01-01T00:00:00Z" }, { "amount": 20000000, "starting_at": "2025-01-01T00:00:00Z", "ending_before": "2026-01-01T00:00:00Z" }, { "amount": 25000000, "starting_at": "2026-01-01T00:00:00Z", "ending_before": "2027-01-01T00:00:00Z" } ] }, "invoice_schedule": { "schedule_items": [ { "amount": 25000000, "timestamp": "2024-01-01T00:00:00Z" }, { "amount": 25000000, "timestamp": "2026-01-01T00:00:00Z" } ] }, "rollover_fraction": 0.25 } ], "overrides": [ { "starting_at": "2024-01-01T00:00:00Z", "type": "multiplier", "multiplier": 0.9, "applicable_product_tags": ["storage"] }, { "starting_at": "2025-01-01T00:00:00Z", "type": "multiplier", "multiplier": 0.8, "applicable_product_tags": ["storage"] } ], "scheduled_charges": [ { "product_id": "0afe45f6-f048-44a5-8fc5-9e9b9592d029", "schedule": { "schedule_items": [ { "amount": 500000, "timestamp": "2024-03-01T00:00:00Z" } ] } } ], "custom_fields": { "sfdc_opportunity_id": "opp_id_01" } }' ``` This API call returns the `contract.id`. Save this ID in your internal database to manage the customer lifecycle in Metronome. ## Optimize your customer’s experience​ The customer journey doesn't end when they sign the contract - consider their experience as they onboard to your product. The customer may adopt your products too slowly, or burn through their prepaid commitment faster than expected. With Metronome, you can provide the end customer with this transparency so they can take action based on their desired usage behaviors. ### Create a cost explorer for your customer​ In this guide’s example, the customer negotiated a discount for storage products. Due to this, they will want to assess what proportion of their usage comes from these features in comparison to others. If they discover it’s a low percentage, they may want to change their discount structure during the next contract negotiation. [Build a cost explorer](/guides/customers-billing/optimize-customer-experience/customer-dashboards-and-reporting) within your product that highlights spend breakdown over time, with the ability to segment or filter on relevant properties like `product.name`. ### Provide spend control​ Beyond transparency, the customer wants additional capabilities to control their consumption. Metronome’s [spend controls](/enhance-customer-experience/customer-controls/) provide the ability to proactively cap spend based on a variety of considerations. For the example customer’s contract, they only have \$50,000 of spend in year 1 compared to \$200,000 in year 2. If adoption occurs quicker than expected, they may want to get notified when they hit a certain threshold, like \$5,000 of spend remaining. This enables them to take action, potentially by negotiating for the year 2 allotment to be accelerated, before going into overage. ## Manage mid-contract changes and renewals​ At some point, your customer may need new contract terms, potentially to change the discounting on their contract or to alter the schedule and amount on their commit. ### Prepare your sales team​ To prepare for this negotiation, Metronome empowers your sales team with granular insights into the customer’s usage with its native [Salesforce connector](/integrations/platform-integrations/sfdc-integration). Metronome can sync important data to the system your sales team operates in, like the balance remaining on a commit, spend by product, usage over time, and more. With access to this data, your sales team can effectively engage the customer with a clear understanding of the value they get from the product. ### Execute an upsell​ Metronome contract edits and transitions help you handle changes to existing contracts. Edit a contract to add terms without starting a new contract. Use a contract transition to start a new contract with a customer. With contract transitions, Metronome keeps track of the relationship with the original contract and applies transition logic like rolling over unused commitments or credits during a renewal. For example, after several conversations with your customer, your InfraX sales team effectively negotiates an upsell on the existing contract on Jan 01, 2025: * In addition to the existing commit, the customer agrees to buy a new \$300,000 commit. * In return for this commit, the customer negotiates a new discount of 15% on `analysis` products. Execute this edit with an API call: ```bash theme={null} curl https://api.metronome.com/v2/contracts/edit \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "13117714-3f05-48e5-a6e9-a66093f13b4d", "contract_id": "d7abd0cd-4ae9-4db7-8676-e986a4ebd8dc", "add_scheduled_charges": [ { "product_id": "76e57c3a-064f-49ad-8740-2bff58f2f808", "schedule": { "schedule_items": [ { "timestamp": "2025-01-01T00:00:00Z", "amount": 30000000 } ] } } ], "add_overrides": [ { "starting_at": "2025-01-01T00:00:00Z", "type": "multiplier", "multiplier": 0.85, "applicable_product_tags": ["analysis"] } ] }' ``` ## Power financial workflows​ Ensure your finance teams are set up for success. As you set up contract and customer objects, you established relationships between entities in different systems. This is critical for workflows like reconciliation, which are an audit performed by finance to ensure the accuracy of information in revenue systems. To learn more about powering finance workflows in Metronome, see: * **[Data reconciliation](/guides/reporting-insights/financial-reporting/reconcile-data)** : By leveraging stored foreign key relationships, determine if all of the necessary data made it from the upstream CRM tool to Metronome to the downstream accounting system. This is a critical process for minimizing revenue leakage when closing the books at the end of the month and demonstrating an audit trail between systems for third-party auditors. * **[Revenue recognition](/guides/reporting-insights/financial-reporting/revenue-recognition)** : Given the appropriate SKU IDs are on the Metronome invoice through product custom fields, effectively map line items to the appropriate revenue buckets in your ERP system. # Guides home Source: https://docs.metronome.com/guides/pricing-packaging/billing-model-guides/guides-home Use the billing model guides below to walk through implementing some of the most common use cases in Metronome. Each guide provides step-by-step instructions to help you configure your specific billing model and get started quickly. # Configure your billing model # Launch a hybrid business model Source: https://docs.metronome.com/guides/pricing-packaging/billing-model-guides/hybrid-business-models Modern SaaS pricing is evolving. Many companies that previously charged a flat rate per seat are now moving toward hybrid pricing models that combine recurring revenue with usage-based components. Metronome supports a wide range of hybrid business models, helping you balance predictability with upside. This guide describes how to launch a hybrid business model using Metronome, including how to: * Create customer contracts * Cut off access to features when the customer runs out of credits * Set up your end-user billing experience ## Use case​ This guide demonstrates a hybrid business model using SeatsCo, a fictional company with an existing seats-based model. In this example, you're introducing SeatsCo's first AI features, and you want to add a usage-based element to your AI products to protect margins and capture upside from power users. Here's how the new *Team plan* pricing model works: * The customer pays \$10/month (or \$100/year) per seat, and each seat includes 100 AI credits per month for AI products. * The AI credits are pooled and available to anyone on the team. Each month's AI credits expire at the end of the month—they are use it or lose it. * The AI credits apply to three AI products: AI Assistant, AI Preview, and AI Summary. * Once the AI credits run out, the customer can no longer use AI functionality on the SeatsCo platform. * The customer can choose to wait until the next month for their AI credits to reset, or they can purchase a top-up pack of credits. Top-up packs have a year-long expiry and cost \$80 for 1,000 credits. When you enable this pricing model, Metronome fully owns the provisioning of credits. This means you don’t need to maintain any code to calculate prorations or grant new credits when the customer signs up for a new seat. **INFO** Another common pricing model is seat-scoped credits, where each seat receives credits only they can use. See [Individual seat credit](/guides/pricing-packaging/subscription/provision-your-customer#individual-seat-credit) to model this use case in Metronome. ## Metronome building blocks​ In Metronome, the [rate card](/guides/get-started/core-concepts/create-manage-rate-cards) is your centralized price book. This is where you encode pricing for all products, including subscriptions and usage-based products. Start by setting up these core Metronome objects: a subscription product, billable metrics, usage products, and a rate card. Hybrid business model ### Create subscription products​ Create a [subscription](/guides/pricing-packaging/billing-model-guides/create-a-subscription) product called Team Plan. This API call shows how to create a subscription product with the [/v1/contract-pricing/products/create](/api-reference/products/create-a-product) endpoint: ```bash theme={null} curl https://api.metronome.com/v1/contract-pricing/products/create \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "Team Plan", "type": "SUBSCRIPTION" }' ``` ### Create usage products​ Create [billable metrics](/guides/get-started/core-concepts/create-billable-metrics/) to track the usage of the AI Assistant, AI Preview, and AI Summary. Then, create [usage products](/guides/get-started/core-concepts/create-products-contracts) referencing those billable metrics. This API call shows how to create a usage product with the [/v1/contract-pricing/products/create](/api-reference/products/create-a-product) endpoint: ```bash theme={null} curl https://api.metronome.com/v1/contract-pricing/products/create \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "AI Assistant", "type": "USAGE", "billable_metric_id": "00ca093f-f347-4dd3-bb9b-9705f1b015e3", "tags": [ "AI Products" ] }' ``` ### Create a rate card with subscription and usage products​ After creating your products, create a [rate card](/guides/get-started/core-concepts/create-manage-rate-cards). When creating the rate card, define the conversion rate between the custom pricing unit *AI credits* and USD. This API call shows how to create a rate card with a credit pricing conversion using the [/v1/contract-pricing/rate-cards/create](/api-reference/rate-cards/create-a-rate-card) endpoint: ```bash theme={null} curl https://api.metronome.com/v1/contract-pricing/rate-cards/create \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "Subscription and Usage Pricebook", "fiat_credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "credit_type_conversions": [ { "custom_credit_type_id": "d3cb2827-dcb5-44af-9354-947a7197b9a6", "fiat_per_custom_credit": 100 } ] }' ``` Next, add the products you just created to the rate card. This API call uses the [/contract-pricing/rate-cards/addRates](/api-reference/rate-cards/add-a-rate) endpoint to add the subscription product Team plan to the rate card with two billing frequencies: monthly and annual. Team plan is priced in USD. It also adds three usage products to the rate card: AI Assistant, AI Preview, and AI Summary, all priced in the custom pricing unit of AI credits. ```bash theme={null} curl https://api.metronome.com/v1/contract-pricing/rate-cards/addRates \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "rate_card_id": "d7abd0cd-4ae9-4db7-8676-e986a4ebd8dc", "rates": [ { "product_id": "76f29162-7f5c-4ee6-89ed-ebbd592d767e", "starting_at": "2025-01-01T00:00:00.000Z", "entitled": true, "rate_type": "FLAT", "price": 10000, "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "billing_frequency": "yearly" }, { "product_id": "76f29162-7f5c-4ee6-89ed-ebbd592d767e", "starting_at": "2025-01-01T00:00:00.000Z", "entitled": true, "rate_type": "FLAT", "price": 1000, "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "billing_frequency": "monthly" }, { "product_id": "2fefe8b6-ca37-4355-a699-0a318e868902", "starting_at": "2025-01-01T00:00:00.000Z", "entitled": true, "rate_type": "FLAT", "price": 12, "credit_type_id": "d3cb2827-dcb5-44af-9354-947a7197b9a6" }, { "product_id": "c3b1ecc0-66ec-4a18-8782-7496c6e05248", "starting_at": "2025-01-01T00:00:00.000Z", "entitled": true, "rate_type": "FLAT", "price": 5, "credit_type_id": "d3cb2827-dcb5-44af-9354-947a7197b9a6" }, { "product_id": "13117714-3f05-48e5-a6e9-a66093f13b4d", "starting_at": "2025-01-01T00:00:00.000Z", "entitled": true, "rate_type": "FLAT", "price": 7, "credit_type_id": "d3cb2827-dcb5-44af-9354-947a7197b9a6" } ] }' ``` At any point you can [update the rate card](/guides/get-started/core-concepts/create-manage-rate-cards#update-a-rate-card%E2%80%8B) to evolve the rates you charge for subscription and usage products. ## Implement a hybrid model for a customer​ A customer’s contract encodes their specific agreement with SeatsCo. To model hybrid pricing models where a seat comes with a given amount of credits, Metronome can link recurring credits and commits to a subscription object. When you increment or decrement the subscription’s quantity, credits are automatically provisioned and tracked based on proration behaviors that you set. ### Create a subscription and linked recurring credit​ Create a [customer contract](/guides/customers-billing/manage-customers/provision-a-customer#provision-a-customer-contract) referencing your rate card. In this example, the customer signed up for the Team plan with an annual payment and an initial quantity of 4 seats. For each seat, the customer receives 100 AI credits in a shared pool monthly. This API call shows how to create the described contract using the [/contracts/create](/api-reference/contracts/create-a-contract) endpoint. The `subscription_config` settings in this example indicate that if the customer adds a seat mid-month, the amount of AI credits granted for that seat get prorated. ```bash theme={null} curl https://api.metronome.com/v1/contracts/create \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "starting_at": "2025-06-01T00:00:00Z", "rate_card_id": "d7abd0cd-4ae9-4db7-8676-e986a4ebd8dc", "customer_id": "d8319d6f-8ee0-43a7-b76f-d7587c0a811c", "subscriptions": [ { "collection_schedule": "advance", "initial_quantity": 4, "proration": { "invoice_behavior": "BILL_IMMEDIATELY", "is_prorated": true }, "subscription_rate": { "billing_frequency": "annual", "product_id": "76f29162-7f5c-4ee6-89ed-ebbd592d767e" }, "temporary_id": "team_plan_annual" } ], "recurring_credits": [ { "access_amount": { "credit_type_id": "d3cb2827-dcb5-44af-9354-947a7197b9a6", "unit_price": 100 }, "commit_duration": { "value": 1, "unit": "periods" }, "priority": 1, "recurrence_frequency": "monthly", "product_id": "652e1298-7638-45a8-b691-cdf47e46cbc8", "starting_at": "2025-06-01T00:00:00Z", "subscription_config": { "subscription_id": "team_plan_annual", "apply_seat_increase_config": { "is_prorated": true } } } ], "billing_provider_configuration": { "billing_provider":"STRIPE" } }' ``` ### Increase seats and automatically provision credits​ When the customer signs up for another seat, [edit the contract](/manage-product-access/edit-contract/) to increment the quantity. You don’t need to touch the credits—Metronome automatically handles their provisioning and proration. This API call shows how to increment the subscription seat quantity using the [editContract](/api-reference/contracts/edit-a-contract) endpoint: ```bash theme={null} curl https://api.metronome.com/v2/contracts/edit \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "customer_id": "d8319d6f-8ee0-43a7-b76f-d7587c0a811c", "contract_id": "d701e556-c30e-4e9c-98af-304782d49345", "update_subscriptions": [ { "subscription_id": "e8cb4466-3e55-485e-b0ae-d83dfc4e82e1", "quantity_updates": [ { "starting_at": "2025-07-03T00:00:00Z", "quantity_delta": 1 } ] } ] }' ``` When a customer removes a seat, decrement the seat quantity. This API call shows how to decrement the quantity using the [editContract](/api-reference/contracts/edit-a-contract) endpoint: ```bash theme={null} curl https://api.metronome.com/v2/contracts/edit \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "customer_id": "d8319d6f-8ee0-43a7-b76f-d7587c0a811c", "contract_id": "d701e556-c30e-4e9c-98af-304782d49345", "update_subscriptions": [ { "subscription_id": "e8cb4466-3e55-485e-b0ae-d83dfc4e82e1", "quantity_updates": [ { "starting_at": "2025-07-10T00:00:00Z", "quantity_delta": -1 } ] } ] }' ``` ### Set threshold notification on credit balance You can set [threshold notifications](/guides/customers-billing/set-up-notifications/create-and-manage-notifications) on credit balance to receive webhooks when the customer is almost out of AI credits and when they've fully depleted their AI credits. Upon receiving these webhooks, you can gate the customer’s access to using any more AI credits until they purchase a top-up credit pack, or the month resets. This API call shows how to create a threshold notification when the customer has 10 AI credits remaining using the [/alerts/create](/api-reference/alerts/create-an-alert) endpoint. ```bash theme={null} curl https://api.metronome.com/v1/alerts/create \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "alert_type": "low_remaining_contract_credit_and_commit_balance_reached", "credit_type_id": "d3cb2827-dcb5-44af-9354-947a7197b9a6", "threshold": 10, "name": "10 AI credits remaining reached", "customer_id": "d8319d6f-8ee0-43a7-b76f-d7587c0a811c" }' ``` ### Enable purchase of top-up credits​ If a customer purchases a top-up credit pack, edit their contract to add the purchased credits. To ensure that the monthly included AI credits are always consumed first, set the priority of the purchased credits to a larger number priority than the priority of the included AI credits. You can choose to [gate these credits](/pricing-packaging/apply-credits-commits/manual-payment-gated-commits/) on payment in Stripe or any other billing provider. If you gate the payment, the credits only release once they're paid for, ensuring you’re protected against fraud. In this example, the customer purchased a pack of top-up credits at the discounted rate of \$80 for 1,000 AI credits. These credits don't expire until a full year after their purchase, unlike the monthly included credits. ```bash theme={null} curl https://api.metronome.com/v2/contracts/edit \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "customer_id": "d8319d6f-8ee0-43a7-b76f-d7587c0a811c", "contract_id": "d701e556-c30e-4e9c-98af-304782d49345", "add_commits": [ { "product_id": "d6be3bf4-1669-40c9-a8b1-388bb167ab16", "type": "prepaid", "invoice_schedule": { "schedule_items": [ { "timestamp": "2025-07-07T00:00:00.000Z", "amount": 8000 } ] }, "access_schedule": { "schedule_items": [ { "amount": 1000, "credit_type_id": "d3cb2827-dcb5-44af-9354-947a7197b9a6", "starting_at": "2025-07-07T00:00:00.000Z", "ending_before": "2026-07-07T00:00:00.000Z" } ] }, "payment_gate_config": { "payment_gate_type": "STRIPE", "tax_type": "STRIPE", "stripe_config": { "payment_type": "PAYMENT_INTENT" } }, "priority": 100 } ] }' ``` ## Optimize your customer's experience​ Use Metronome to offer your customers robust billing experiences. ### Create the customer billing experience​ With SeatsCo's new usage-based pricing component, it's important to provide a more robust customer billing experience, so customers have real-time visibility into their remaining balance and can set cost controls on a per-seat basis. ### Get the balance of the credit​ Use the [listCustomerBalances](/api-reference/credits-and-commits/list-balances) endpoint to show the current balance in AI credits, inclusive of usage by all seats. ### Set cost controls per seat​ The administrator of a team may want to cap the number of AI credits an individual user can spend. To do this, pass in the `user_id` performing an action in your event data, and set that `user_id` as a [group key](/guides/get-started/core-concepts/create-billable-metrics#3-define-group-keys%E2%80%8B) on the relevant billable metrics. Then, create a spend alert for a specific `user_id`. You can cut the user off from spending more AI credits, notify their administrator, or notify them. For example, this example spend alert sends a webhook notification when `user_id = user_1234` spends more than 1,000 AI credits in the billing period. ```bash theme={null} curl https://api.metronome.com/v1/alerts/create \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "alert_type": "spend_threshold_reached", "credit_type_id": "d3cb2827-dcb5-44af-9354-947a7197b9a6", "name": "user_1234 AI credit spend alert", "threshold": 1000, "customer_id": "d8319d6f-8ee0-43a7-b76f-d7587c0a811c", "group_values": [{ "key": "user_id", "value": "user_1234" }] }' ``` ## Conclusion​ SeatsCo is now ready to launch AI features with their new hybrid business model! They've set up a subscription plan with AI credits per seat, automatic provisioning and proration as seats are added or removed, low credit balance alerts, and the ability for customers to purchase top-up credits. SeatsCo also provides customers a transparent billing experience, with clear visibility into usage and spend controls. # Model hierarchical customer relationships Source: https://docs.metronome.com/guides/pricing-packaging/billing-model-guides/model-hierarchical-customer-relationships For companies with direct sales motions selling to multiple organizational levels, account hierarchies enable you to model complex parent-child relationships in Metronome. This feature supports enterprise contracting scenarios where parent organizations may be responsible for subsidiary usage, commitments, and billing across different sub organizations. ## Overview Account hierarchies allow you to: * Model parent-child relationships between distinct Metronome customers (up to 10 nodes) * Share commits and credits across hierarchical levels * Configure flexible payment arrangements (parent pays, child pays, or mixed) * Consolidate child usage onto a single invoice at the parent level * Maintain distinct pricing and contracts for each entity Consider a multinational corporation like Disney contracting with a cloud infrastructure provider for content delivery services. Disney and its subsidiaries (Hulu, ESPN, ABC) stream massive amounts of video content, paying for each gigabyte of data transferred through the provider's CDN. With account hierarchies, you can configure various billing models: * Disney could pay for all CDN data transfer across subsidiaries while each maintains their own contracts and pricing * Disney could purchase a \$10M shared commit for CDN data transfer that Hulu, ESPN, and other subsidiaries draw from before paying overages * Each subsidiary could have their own pricing and commits, with Disney receiving a single consolidated invoice showing detailed usage breakdowns ## Prerequisites Before implementing account hierarchies, ensure you have: * Customer objects created for both parent and child organizations * A billing configuration set up for each customer. Currently, Stripe billing is supported. * Understanding of your organizational billing structure and payment flows Note: Hierarchy relationships are configured during contract creation, not as a separate step. ### Example 1: Parent with shared commit pool In this scenario, Disney purchases a \$10M commit that all subsidiaries can access for their usage. Create the parent contract with shared commit: ```bash theme={null} curl -X POST https://api.metronome.com/v1/contracts/create \ -H "Authorization: Bearer $METRONOME_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "customer_id": "disney_parent_id", "name": "Disney Master Agreement", "rate_card_id": "enterprise_rate_card_id", "starting_at": "2025-01-01T00:00:00Z", "commits": [{ "type": "prepaid", "product_id": "prepaid_commit_product_id", "access_schedule": { "schedule_items": [{ "amount": 10000000, "starting_at": "2025-01-01T00:00:00Z", "ending_before": "2026-01-01T00:00:00Z" }] }, "invoice_schedule": { "schedule_items": [{ "amount": 10000000, "timestamp": "2025-01-01T00:00:00Z" }] }, "hierarchy_configuration": { "child_access": { "type": "all" } } }] }' ``` Create child contracts that can access the shared commit: ```bash theme={null} # Hulu contract - pays for own overages curl -X POST https://api.metronome.com/v1/contracts/create \ -H "Authorization: Bearer $METRONOME_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "customer_id": "hulu_customer_id", "name": "Hulu - Disney Subsidiary", "rate_card_id": "enterprise_rate_card_id", "starting_at": "2025-01-01T00:00:00Z", "hierarchy_configuration": { "parent": { "contract_id": "disney_contract_id", "customer_id": "disney_parent_id" }, "payer": "SELF", "usage_statement_behavior": "SEPARATE" } }' # ESPN contract - pays for own overages curl -X POST https://api.metronome.com/v1/contracts/create \ -H "Authorization: Bearer $METRONOME_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "customer_id": "espn_customer_id", "name": "ESPN - Disney Subsidiary", "rate_card_id": "enterprise_rate_card_id", "starting_at": "2025-01-01T00:00:00Z", "hierarchy_configuration": { "parent": { "contract_id": "disney_contract_id", "customer_id": "disney_parent_id" }, "payer": "SELF", "usage_statement_behavior": "SEPARATE" } }' ``` In this setup: * All children draw from Disney's \$10M commit * Each child pays their own overages once the shared commit is exhausted * Each child receives their own invoices ### Example 2: Parent pays with consolidated invoicing In this scenario, each subsidiary has their own commits, but Disney receives and pays all invoices with usage consolidated into a single statement. Create the parent contract with invoice consolidation enabled: ```bash theme={null} curl -X POST https://api.metronome.com/v1/contracts/create \ -H "Authorization: Bearer $METRONOME_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "customer_id": "disney_parent_id", "name": "Disney Master Agreement - Consolidated Billing", "rate_card_id": "enterprise_rate_card_id", "starting_at": "2025-01-01T00:00:00Z", "hierarchy_configuration": { "parent_behavior": { "invoice_consolidation_type": "CONCATENATE" } }, "commits": [{ "type": "prepaid", "product_id": "prepaid_commit_product_id", "access_schedule": { "schedule_items": [{ "amount": 200000, "starting_at": "2025-01-01T00:00:00Z", "ending_before": "2026-01-01T00:00:00Z" }] }, "invoice_schedule": { "schedule_items": [{ "amount": 200000, "timestamp": "2025-01-01T00:00:00Z" }] }, "hierarchy_configuration": { "child_access": { "type": "none" } } }] }' ``` Create child contracts with parent as payer: ```bash theme={null} # Hulu with its own commit, parent pays curl -X POST https://api.metronome.com/v1/contracts/create \ -H "Authorization: Bearer $METRONOME_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "customer_id": "hulu_customer_id", "name": "Hulu - Disney Subsidiary", "rate_card_id": "enterprise_rate_card_id", "starting_at": "2025-01-01T00:00:00Z", "hierarchy_configuration": { "parent": { "contract_id": "disney_contract_id", "customer_id": "disney_parent_id" }, "payer": "PARENT", "usage_statement_behavior": "CONSOLIDATE" }, "commits": [{ "type": "prepaid", "product_id": "prepaid_commit_product_id", "access_schedule": { "schedule_items": [{ "amount": 500000, "starting_at": "2025-01-01T00:00:00Z", "ending_before": "2026-01-01T00:00:00Z" }] }, "invoice_schedule": { "schedule_items": [{ "amount": 500000, "timestamp": "2025-01-01T00:00:00Z" }] } }] }' ``` In this setup: * Disney has its own \$200K commit that only it can access (child\_access: "none") * Hulu has its own \$500K commit that only it can access * Disney pays for all commits including Hulu's \$500K commit invoice * Disney receives a single consolidated usage statement invoice containing Disney's own usage and Hulu’s usage with line items indicating the origin customer and contract * All invoices are routed to Disney’s billing provider Note: Even in a consolidation scenario, all children and the parent will still have their own standalone usage statements generated by Metronome which will be visible over Metronome’s UI, API and data export. These standalone usage statements will not, however, be sent to downstream billing providers when consolidation is set to occur. You may wish to filter out the standalone parent usage statement when showing spend detail to the parent in your UI so as to not double count parent spend across the standalone and consolidated invoices. ### Example 3: Selective commit access with distinct pricing In this scenario, Disney has multiple commits with selective access, and each subsidiary has custom pricing. Create parent contract: ```bash theme={null} curl -X POST https://api.metronome.com/v1/contracts/create \ -H "Authorization: Bearer $METRONOME_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "customer_id": "disney_parent_id", "name": "Disney Master Agreement - Selective Access", "rate_card_id": "enterprise_rate_card_id", "starting_at": "2025-01-01T00:00:00Z" }' ``` Create child contracts with pricing overrides: ```bash theme={null} # Hulu with 20% discount on cdn data transfer curl -X POST https://api.metronome.com/v1/contracts/create \ -H "Authorization: Bearer $METRONOME_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "customer_id": "hulu_customer_id", "name": "Hulu - Disney Subsidiary", "rate_card_id": "streaming_rate_card_id", "starting_at": "2025-01-01T00:00:00Z", "hierarchy_configuration": { "parent": { "contract_id": "disney_contract_id", "customer_id": "disney_parent_id" }, "payer": "SELF", "usage_statement_behavior": "SEPARATE" }, "overrides": [{ "product_id": "cdn_data_transfer_gb_id", "multiplier": 0.8 }] }' # ABC (no access to premium commit) curl -X POST https://api.metronome.com/v1/contracts/create \ -H "Authorization: Bearer $METRONOME_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "customer_id": "abc_customer_id", "name": "ABC - Disney Subsidiary", "rate_card_id": "broadcast_rate_card_id", "starting_at": "2025-01-01T00:00:00Z", "hierarchy_configuration": { "parent": { "contract_id": "disney_contract_id", "customer_id": "disney_parent_id" }, "payer": "SELF", "usage_statement_behavior": "SEPARATE" } }' ``` Add shared commits with selective access to parent contract: ```bash theme={null} curl -X POST https://api.metronome.com/v2/contracts/edit \ -H "Authorization: Bearer $METRONOME_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "customer_id": "disney_parent_id", "contract_id": "disney_contract_id", "starting_at": "2025-01-01T00:00:00Z", "add_commits": [{ "type": "prepaid", "name": "Premium Infrastructure Commit - Streaming Only", "product_id": "prepaid_commit_product_id", "applicable_product_ids": ["premium_cdn_transfer_gb"], "access_schedule": { "schedule_items": [{ "amount": 5000000, "starting_at": "2025-01-01T00:00:00Z", "ending_before": "2026-01-01T00:00:00Z" }] }, "invoice_schedule": { "schedule_items": [{ "amount": 5000000, "timestamp": "2025-01-01T00:00:00Z" }] }, "hierarchy_configuration": { "child_access": { "type": "contract_ids", "contract_ids": ["hulu_contract_id", "espn_contract_id"] } } }, { "type": "prepaid", "name": "Standard Infrastructure Commit - All Properties", "product_id": "prepaid_commit_product_id_2", "applicable_product_ids": ["standard_cdn_transfer_gb"], "access_schedule": { "schedule_items": [{ "amount": 2000000, "starting_at": "2025-01-01T00:00:00Z", "ending_before": "2026-01-01T00:00:00Z" }] }, "invoice_schedule": { "schedule_items": [{ "amount": 2000000, "timestamp": "2025-01-01T00:00:00Z" }] }, "hierarchy_configuration": { "child_access": { "type": "all" } } }] }' ``` In this setup: * Different rate cards: Each subsidiary uses a rate card tailored to their business (streaming vs. broadcast) with appropriate products and pricing * Selective commit access: Hulu and ESPN can access both premium and standard commits, while ABC only accesses the standard commit * Contract-specific pricing: Hulu gets 20% off GB of CDN data transfer when drawing from the premium commit or paying overages * Individual billing: Each subsidiary pays for their own overages and maintains separate billing configurations ## Viewing hierarchy relationships ### Get contract with hierarchy details Retrieve complete hierarchy information for any contract: ```bash theme={null} curl -X POST https://api.metronome.com/v2/contracts/get \ -H "Authorization: Bearer $METRONOME_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "customer_id": "disney_parent_id", "contract_id": "disney_contract_id" }' ``` Parent contracts show their children: ``` { "hierarchy_configuration": { "parent_behavior": { "invoice_consolidation_type": "CONCATENATE" }, "children": [{ "contract_id": "hulu_contract_id", "customer_id": "hulu_customer_id" }, { "contract_id": "espn_contract_id", "customer_id": "espn_customer_id" }] } } ``` ### View consolidated invoices When configured for consolidation, parent invoices include all subsidiary usage: ```bash theme={null} curl -X POST https://api.metronome.com/v1/invoices/get \ -H "Authorization: Bearer $METRONOME_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "customer_id": "disney_parent_id", "invoice_id": "consolidated_invoice_id" }' ``` Response includes origin details for each line item: ``` { "type": "USAGE_CONSOLIDATED", "constituent_invoices": [ {"invoice_id": "parent_invoice", "customer_id": "disney_parent_id", "contract_id": "disney_contract_id"}, {"invoice_id": "hulu_invoice", "customer_id": "hulu_customer_id", "contract_id": "hulu_contract_id"}, {"invoice_id": "espn_invoice", "customer_id": "espn_customer_id", "contract_id": "espn_contract_id"} ], "line_items": [{ "type": "usage", "amount": 15000, "product_id": "streaming_compute_id", "origin": { "invoice_id": "hulu_invoice", "line_item_id": "hulu_line_item_id", "contract_id": "hulu_contract_id", "customer_id": "hulu_customer_id" } }] } ``` ### Break down consolidated invoices Analyze usage distribution across the hierarchy using invoice breakdowns. This is particularly useful for understanding spend patterns across subsidiaries. ```bash theme={null} curl -X POST https://api.metronome.com/v1/invoices/breakdown \ -H "Authorization: Bearer $METRONOME_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "customer_id": "disney_parent_id", "invoice_id": "consolidated_invoice_id", "breakdown_start_timestamp": "2025-01-01T00:00:00Z", "breakdown_end_timestamp": "2025-01-02T00:00:00Z" }' ``` The breakdown response for consolidated invoices includes origin information for each line item: ``` { "breakdown_start_timestamp": "2025-01-01T00:00:00Z", "breakdown_end_timestamp": "2025-01-02T00:00:00Z", "id": "consolidated_invoice_id", "customer_id": "disney_parent_id", "type": "USAGE_CONSOLIDATED", "line_items": [ { "amount": 15000, "product_id": "cdn_data_transfer_gb_id", "quantity": 1500, "unit_price": 10, "timestamp": "2025-01-01T08:00:00Z", "origin": { "invoice_id": "hulu_usage_invoice_123", "contract_id": "hulu_contract_id", "customer_id": "hulu_customer_id" } }, { "amount": 8000, "product_id": "cdn_data_transfer_gb_id", "quantity": 800, "unit_price": 10, "timestamp": "2025-01-01T14:00:00Z", "origin": { "invoice_id": "espn_usage_invoice_456", "contract_id": "espn_contract_id", "customer_id": "espn_customer_id" } }, { "amount": 5000, "product_id": "cdn_data_transfer_gb_id", "quantity": 500, "unit_price": 10, "timestamp": "2025-01-01T20:00:00Z", "origin": { "invoice_id": "disney_usage_invoice_789", "contract_id": "disney_contract_id", "customer_id": "disney_parent_id" } } ] } ``` Use the origin information to: * Analyze spend by subsidiary: Group line items by `origin.customer_id` to see each entity's usage * Track contract performance: Use `origin.contract_id` to measure usage against specific contracts ## Best practices **Design your hierarchy thoughtfully** * Map organizational relationships before implementation * Consider payment flows and invoice routing requirements **Set clear commit access rules** * Use `type: "all"` for organization-wide shared resources * Use `type: "contract_ids"` for department or tier-specific access **Monitor usage patterns** * Review consolidated invoices to understand usage distribution * Use invoice breakdowns to analyze spending by subsidiary **Coordinate contract timing** * Align contract start dates when possible * Plan renewal strategies across the hierarchy * Consider commit rollover implications for renewals ## Troubleshooting **Child cannot access parent commit** * Verify the parent commit's `child_access` configuration includes the child * Ensure the child contract correctly references the parent contract ID * Confirm both contracts are active during the same time period **Child invoices not appearing on consolidated invoice:** * Verify parent contract has `invoice_consolidation_type: "CONCATENATE"` * Check child contract has `usage_statement_behavior: "CONSOLIDATE"` * Ensure child's usage service period is bounded by parent's service period * Example: If parent invoice covers Jan 1-31 and child invoice covers Jan 5-31, child usage will consolidate. But if child invoice covers Dec 28 - Jan 28, child usage will not consolidate * Confirm the issue dates align (same day) between parent and child invoices **Cannot set consolidation with self-payment:** * `usage_statement_behavior: "CONSOLIDATE"` requires `payer: "PARENT"` * Child contracts paying themselves must use `usage_statement_behavior: "SEPARATE"` ## Current limitations 1. **Hierarchy depth**: Only one level supported (parent-child); no grandchildren or multi-level hierarchies 2. **Hierarchy size**: Maximum active 10 nodes supported in a hierarchy 3. **Billing providers**: Only Stripe is supported; marketplace billing coming soon 4. **Contract structure**: Each Metronome customer requires their own contract - no single contract can automatically apply to all children 5. **Usage rating**: Each child's usage is rated separately based on their contract. Parent tiered pricing only applies to direct parent usage, not aggregated child usage 6. **Alert scope**: * Commit balance alerts on parent contracts don't automatically trigger when children consume the commit * Alerts evaluate when the parent receives usage data * If only children receive usage, parent alerts may be delayed until parent usage arrives * Additionally, parent spend alerts only include parent's 7. **Embeddable dashboards**: Invoice and commit dashboards don't work with customers that have a contract in a hierarchy # Launch a pay-as-you-go business model Source: https://docs.metronome.com/guides/pricing-packaging/billing-model-guides/pay-as-you-go PayGo (pay-as-you-go) refers to a consumption-based pricing model where businesses pay only for the software resources or features they use in arrears, instead of committing to a fixed subscription or long-term contract. This model has become increasingly popular, especially in cloud-based solutions and SaaS platforms, due to its flexibility, scalability, and cost-efficiency. Typically, customers sign up directly on a company’s website, often at the list price, without needing to talk to a company representative. Given the limited friction in accessing the product, PayGo motions are ideal for product lines where customer growth is a key goal. PayGo motions are used by companies at varying scales: * New startups launching their first product * Public companies maintaining existing B2C product lines * Transforming companies augmenting their legacy subscription business models with a new usage product In this guide you'll learn how to implement a PayGo business on Metronome. ## Use case​ The fictional company used in this guide, called AutoSales, has just come out of stealth and wants to sell on the market for the first time. This is a sales-tech company focused on automating top-of-funnel processes to help companies identify and qualify leads faster. AutoSales has four core products: * **Automated email generation** detects visitors on a website and automatically sends them an email offering to connect with a sales representative. * **Automated reminders** scrapes an email inbox and flags emails that should be followed up on. This might be because a prospect hasn't responded after X days or because a prospect reached out but hasn't received a reply. * **Spreadsheet updates** automatically creates a tracker in a spreadsheet that captures prospect information and communication history with them. * **Slack integration** spins up a Slack room for a qualified prospect. The company initially offers three models: Basic, Better, and Best, which price and package their products differently. Each package is an example of a PayGo configuration. | **Basic** | **Better** | **Best** | | --------------------------------------------- | --------------------------------------------- | ------------------------------------------------------------------ | | Email generation at \$0.10 per email | Email generation at \$0.10 per email | Email generation at \$0.10 per email | | Spreadsheets updates at \$0.15 per row update | Spreadsheets updates at \$0.15 per row update | Spreadsheets updates at \$0.15 per row update | | | Automated reminders at \$0.20 per reminder | Automated reminders at \$0.20 per reminder | | | Slack integration at \$0.10 per Slack room | Slack integration at \$0.10 per Slack room | | | | Configurable AI model to personalize automations at \$10 per month | ## Metronome building blocks​ For AutoSales to implement pay-as-you-go, the first step is to get Metronome set up. Here's what you need to set up to enable this sales motion: * [Send events data](/guides/get-started/core-concepts/send-usage-events) streaming into Metronome to track the usage of each product per customer. * [Create five products](/guides/get-started/core-concepts/create-products-contracts) in Metronome. For AutoSales, they have five products, where four represent each of the usage products, and the fifth represents the monthly fee for configuring an AI model. To expedite the provisioning process, they should tag products that are only on the Better and Best bundles with a `premium` tag. * [Create one rate card](/guides/get-started/core-concepts/create-manage-rate-cards). For AutoSales, their rate card has the standard pricing for all four usage products with `entitlements` set to `true`. You can later disable access to certain products based on the plan the customer chooses. * (Optional) [Set up a Stripe integration](/integrations/invoice-integrations/stripe). For this example, AutoSales uses Stripe for their invoicing and payments, which is common for Metronome customers implementing a PayGo motion. However, end invoicing and payment workflows can be configured to other destinations. AutoSales rate card ## Implement a pay-as-you-go model​ Follow this guide to build a pay-as-you-go model in Metronome. ### Sign up customers​ Looking ahead in the fictional scenario, AutoSales has officially launched their product and has their listing live on their website. Within minutes, they have a customer signed up for their Basic plan. To execute an initial customer sign-up in Metronome: 1. **Create the customer in Stripe.** As the payment processor, Stripe needs to have the credit card information of the customer. After the customer signs up on their website, AutoSales needs to create the customer in Stripe and add the credit card as the preferred payment method. To learn how to do this, go to [Stripe’s docs](https://docs.stripe.com/api/customers/create). By creating the customer in Stripe first, the Stripe customer ID can be added to the Metronome object. This enables Metronome to map the entities between both systems and automatically invoice the customer. 2. **Create the customer in Metronome.** See this example payload that’s sent to the `/customers` endpoint: ```bash theme={null} curl https://api.metronome.com/v1/customers \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "ingest_aliases": [ "team@customer.com" ], "name": "First Customer", "customer_billing_provider_configurations": [ { "billing_provider": "stripe", "delivery_method": "direct_to_billing_provider", "configuration": { "stripe_customer_id": "stripe001", "stripe_collection_method": "send_invoice" } } ] }' ``` The response to this call returns the Metronome `customer.id`, needed for the next step. 3. **Provision the customer with the Basic contract.** Now that the customer exists, create a contract and configure the rate card to match the desired plan. For this new customer, provision the Basic plan. As the Basic plan only includes two out of the four usage products, create an override on the contract to model this. See this example payload that’s sent to the `/contracts/create` endpoint: ```bash theme={null} curl https://api.metronome.com/v1/contracts/create \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "43ae3f41-480b-412b-9b05-1c4d11169c09", "rate_card_id": "40c0661e-d3ee-4080-88e7-4d3a7ed619d8", "starting_at": "2024-10-01T00:00:00Z", "name": "Basic Contract", "overrides": [ { "starting_at": "2024-10-01T00:00:00Z", "entitled": false, "applicable_product_tags": [ "premium" ] } ] }' ``` This returns the generated `contract.id` . It’s useful to store this information in an internal database for use later on, like for upgrades. As the request didn’t specify any billing schedule, the usage invoice defaults to bill monthly. 4. **Provide access and start billing.** Now that the contract exists in Metronome and the customer is linked to its Stripe counterpart, the customer can have access to the service. Metronome begins billing them automatically! ### Upgrade customers​ Looking ahead, AutoSales’ customer loves their experience and wants to upgrade to the Best bundle to take advantage of the additional features. From AutoSales’ website, they can self-serve this upgrade. They sign up for 6 months and reevaluate from there. For AutoSales to execute this in Metronome, they need to: 1. **End the current contract.** Using the stored `contract.id` from the previous phase, end the current contract for the customer using the `/contracts/updateEndDate` endpoint: ```bash theme={null} curl https://api.metronome.com/v1/contracts/updateEndDate \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "43ae3f41-480b-412b-9b05-1c4d11169c09", "contract_id": "19nm9k87-754b-423p-4m33-2s5q34377v12", "ending_before": "2025-02-01T00:00:00Z" }' ``` 2. **Create a new contract for the Best bundle.** Now that the previous contract has ended, provision access based on the terms of the Best offering: ```bash theme={null} curl https://api.metronome.com/v1/contracts/create \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "43ae3f41-480b-412b-9b05-1c4d11169c09", "rate_card_id": "40c0661e-d3ee-4080-88e7-4d3a7ed619d8", "starting_at": "2025-02-01T00:00:00Z", "ending_at": "2025-08-01T00:00:00Z", "name": "Best Contract", "scheduled_charges": [ { "product_id": "609e4cf2-6ea2-4b07-a46c-6596f041b69e", "schedule": { "recurring_schedule": { "starting_at": "2025-02-01T00:00:00Z", "ending_before": "2025-08-01T00:00:00Z", "frequency": "monthly", "amount": 10000, "amount_distribution": "each" } } } ] }' ``` 3. **Provide access to Best features and bill the customer.** Once the new contract is in place, the customer can start using the new products offered by the Best bundle. The new `contract.id` must be saved internally. As before, the customer gets billed monthly in Stripe. # Launch a prepaid credits business model Source: https://docs.metronome.com/guides/pricing-packaging/billing-model-guides/prepaid-credits Prepaid credits refers to a payment model where customers purchase a batch of credits upfront. These credits are then consumed as the customer uses your software's resources or features. Unlike pay-as-you-go models, users must maintain a positive credit balance to continue accessing your platform's services. Once credits are fully depleted, a user’s access suspends until they purchase additional credits. The prepaid credits model creates a clear pay-before-you-use framework that's gained traction across various SaaS platforms, particularly those concerned with reducing financial risk. Customers typically purchase credit packages through a company's website, selecting from predefined amounts based on their anticipated usage needs. Companies implement prepaid credits models at different stages. For example: * Risk-conscious startups seeking to eliminate payment defaults * Established companies looking to reduce revenue leakage and churn * Businesses operating in markets with higher fraud potential In this guide, you'll learn how to implement a prepaid credits business model on Metronome, including setting up auto-recharge options that allow users to maintain uninterrupted service while preserving your upfront payment requirement. ## Use case​ In this guide, your customer Example Inc. signs up for your platform using Stripe as your billing provider. They purchase 2,000 credits to use on your platform, which expire after one year. When the Example Inc. user clicks `purchase credits` in your system, payment is immediately triggered, and credits are only granted once payment is confirmed successful. With credits in hand, they can use your system and watch their credit balance decrease in real time. Once their balance reaches zero, your system should cut them off from further use until they purchase another batch of credits. ## Metronome building blocks​ Regardless of the commercial model you choose, Metronome’s core job is to turn usage data into accurate spend data. Before implementing the prepaid credit model, set up these core Metronome objects: * [Billable metrics](/guides/get-started/core-concepts/create-billable-metrics/): Create a billable metric for each unit of what customers consume by using your platform (like compute, storage, or API calls). * [Product](/guides/get-started/core-concepts/create-products-contracts): Create a usage-based product for each of your billable metrics so you can configure how your usage spend appears to your users. Also create a fixed product to represent the credit-purchased charges. * [Rate card](/guides/get-started/core-concepts/create-manage-rate-cards) and rates: Create a rate card that contains the burn-down rates for each of the usage-based products that you plan to offer to your users. To learn how to set up these objects, see the [Quickstart](/launch-guides/quickstart/). ## Implement prepaid credits​ After completing this guide, you’ll have a prepaid credits model built out in Metronome. Prepaid credits model ### Set up a billing provider​ Within the prepaid credit flow, Metronome facilitates payment from your billing provider to immediately charge customers and ensure that payments complete before credits are granted. As such, you first need to connect your billing provider to allow Metronome to send and finalize invoices on your behalf. The most common billing provider in the prepaid credits flow is Stripe. To learn how to connect your Stripe account, see [Invoice with Stripe](/integrations/invoice-integrations/stripe). ### Set up a webhook​ The prepaid credits flow relies on your system receiving real-time webhook notifications from Metronome. These are used to send a signal: * When users run out of balance, so that your system can cut off their platform access * Upon successful or failed payment, so that your system can enable or disable customers as needed Before starting, ensure that you have a [webhook destination](/guides/platform-configuration/setup-webhooks) set up to receive requests from Metronome. ### Configure the credit lifecycle​ Implementing a prepaid credits model on Metronome involves taking steps at different parts of the purchase lifecycle. #### Customer sign-up​ When a customer signs up in your application: * Ensure that you've created their customer record in Metronome and your billing provider (for example, Stripe). * Start their contract to encode the rates that Metronome should use as customer usage events start to flow through the system. The end-to-end flow to purchase when using Stripe is: 1. A user signs up for an account in your platform, entering their credit card information. 2. You create the user as a customer in Stripe. 3. You set their entered payment method as their default in Stripe. 4. You create a customer in Metronome, linking the Stripe customer ID. 5. You create a contract for the customer in Metronome. **TIP** We recommend configuring contracts with first of the month billing. While users won't get billed in arrears in a prepaid credits model, using first of the month billing makes it easier to group spend revenue data by monthly boundaries. See this example of using the `customers` endpoint to create a customer, linking to the customer's Stripe customer ID: ```bash theme={null} curl https://api.metronome.com/v1/customers \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "ingest_aliases": [ "team@example.com" ], "name": "Example, Inc.", "customer_billing_provider_configurations": [ { "billing_provider": "stripe", "delivery_method": "direct_to_billing_provider", "configuration": { "stripe_customer_id": "cus_123", "stripe_collection_method": "charge_automatically" } } ] }' ``` See this example of using the `contracts/create` endpoint to create a contract: ```bash theme={null} curl https://api.metronome.com/v1/contracts/create \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "customer_id": "13117714-3f05-48e5-a6e9-a66093f13b4d", "rate_card_id": "d7abd0cd-4ae9-4db7-8676-e986a4ebd8dc", "starting_at": "2025-04-15T00:00:00.000Z", "billing_provider_configuration": { "billing_provider": "stripe", "delivery_method": "direct_to_billing_provider" } }' ``` As users haven't purchased any credits yet, their default entitlement state in your system should be `false`. #### Credit purchases​ In a prepaid credits model, customers must have a positive credit balance to be able to use your system. To have a positive credit balance, they must purchase batches of credits. This is generally included in the initial sign-up flow, and customers then have the ability to purchase ad-hoc credits through your platform as needed. This flow should look like: 1. User clicks **purchase credits in your platform** with the desired amount. 2. You send an API request to Metronome to facilitate the end-to-end prepaid credit. Metronome initiates the payment in Stripe. * Upon success, Metronome creates a commit object to increase the customer balance and sends a webhook with notice of a successful payment. * Upon failure, Metronome voids the commit object in the system and sends a webhook with notice of a failed payment. 3. Upon successful payment, you set a customer's entitlement state to `true` to allow them to start to spend. See this example of using the `contracts/edit` endpoint to facilitate the prepaid credit: ```bash theme={null} curl https://api.metronome.com/v2/contracts/edit \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "customer_id": "13117714-3f05-48e5-a6e9-a66093f13b4d", "contract_id": "d7abd0cd-4ae9-4db7-8676-e986a4ebd8dc", "add_commits": [ { "product_id": "d7abd0cd-4ae9-4db7-8676-e986a4ebd8dc", "access_schedule": { "schedule_items": [ { "amount": 2000, "ending_before": "2025-04-01T00:00:00.000Z", "starting_at": "2026-04-01T00:00:00.000Z" } ] }, "invoice_schedule": { "schedule_items": [ { "amount": 2000, "timestamp": "2025-04-01T00:00:00.000Z" } ] }, "priority": 10, "payment_gate_config": { "payment_gate_type": "STRIPE" } } ] }' ``` #### Manage entitlement​ We recommend that a customer’s entitlement state is managed within your system and database. At its most simple, this could be a true/false value for a particular customer that's checked before they take an action. We recommend that this is maintained within your system so that it can be fetched with the latency that your system will require, and so that it's resilient to any failures between your system and Metronome. At a high level, when a customer action is taken, this is the state you should check: ```javascript theme={null} if (customer_entitled) { do_action(); send_usage_to_metronome(); } else { error("Not enough credits"); } ``` The customer entitlement state should be informed by whether the customer has an active balance. As such, you should use real-time signals from Metronome to drive the state of this customer entitlement flag. The primary mechanism that we recommend for this is to set an alert for all customers to send when customer balance reaches \$0. This way, Metronome sends you a signal when each customer runs out of credits to change their entitlement state. Here's an example of a webhook for when a customer reaches 0. This is your signal to set a customer’s `customer_entitled` to `false`. ```json theme={null} { "id": "8d9cebd2-9c57-4a35-a468-bd73fa2ffa89", "properties": { "customer_id": "ac39ecc3-87ee-4d58-8ec0-24041464a5dd", "alert_id": "618a4ca8-c8d9-4822-addc-bd3008eb8428", "timestamp": "2025-04-07T15:08:44.865Z", "threshold": 0, "alert_name": "Balance low", "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "remaining_balance": 0, "triggered_by": "usage" }, "type": "alerts.low_remaining_contract_credit_and_commit_balance_reached" } ``` ## Optimize your customer's experience​ Use Metronome to offer experiences to your customers like automatic recharge and spend previews. ### Enable automatic recharge​ You can offer automatic recharge to your customers. This allows them to automatically purchase more credits when a threshold is reached, ensuring that they never reach a \$0 balance. For instance, a customer may opt to the following: when my balance reaches \$5 remaining, recharge me back to \$20. If implemented, they should expect increments of \$15 credit purchases after the initial \$20 purchase. You can set up a customer’s desired auto recharge threshold on their contract object. Once set up, Metronome handles all of the recharge actions asynchronously based on customer usage. To set this up, use the `threshold_billing_configuration` object within the create contract request: ```bash theme={null} curl https://api.staging.metronome.com/v1/contracts/create \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "customer_id": "f7ed0bb0-7079-4fd1-baa8-713bf70dcb3b", "rate_card_id": "8664db91-4c22-459a-b3c5-5fb11ce085fe", "starting_at": "2025-04-01T00:00:00.000Z", "credit_balance_threshold_configuration": { "is_enabled": true, "threshold_amount": 300, "recharge_to_amount": 2000, "payment_gate_config": { "payment_gate_type": "STRIPE" }, "commit": { "product_id": "ff6c5ff2-28d9-443c-bb49-68df8191b05f" } } }' ``` Once set up, Metronome handles all of the recharge actions asynchronously based on customer usage. As payments happen, Metronome sends webhooks to your system indicating if payments succeed or fail in the billing provider. In the event of payment failure, Metronome sets the status of the recharge settings `is_enabled` to `false`. To remediate, we recommend sending an email or in-platform notification to the customer prompting them to update their billing information. Upon update of this information, you should edit the contract and `set is_enabled` back to `true`, which triggers another recharge. ### Present spend to your customers​ As a customer’s experience with your platform changes when they run out of credits, you should give them the ability to see their balance updated in real time through your platform. The Metronome [listBalances API](/api-reference/credits-and-commits/list-balances) supports these UI components. This API call shows how to fetch the balance for a particular customer: ```bash theme={null} curl https://api.metronome.com/v1/contracts/customerBalances/list \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "customer_id": "13117714-3f05-48e5-a6e9-a66093f13b4d", "id": "6162d87b-e5db-4a33-b7f2-76ce6ead4e85", "include_balance": true, "include_contracts_balances": true }' ``` This example table shows how you could display this information to your customer: Commit tracking table To view more common workflows for displaying spend data within your application, see [Build API-powered customer dashboards](/guides/customers-billing/optimize-customer-experience/customer-dashboards-and-reporting). # Token Billing Source: https://docs.metronome.com/guides/pricing-packaging/billing-model-guides/token-billing Many companies pass through the cost of LLM tokens to their customers, adding a markup to remain margin-positive. This guide describes how to bill customers for AI usage by token consumption in Metronome, including: * Selecting common models from Anthropic, OpenAI, Google, and other providers * Creating billable metrics, products, and rates based on your configured markup percentage(s) * Automatically syncing newly released models and provider token price changes to your rate card at your configured markup **Private preview** Token Billing is in private preview. To request access, contact us via the [Metronome support portal](https://support.metronome.com/) or [sign up for the waitlist](https://docs.stripe.com/billing/token-billing). ## Set up with an AI coding agent Use the [Metronome Token Billing skill](/.well-known/agent-skills/metronome-token-billing/skill.md) to guide an AI coding agent through a sandbox integration. Open your application repository, then copy and paste this prompt into your agent: ```text wrap theme={null} Use the Metronome Token Billing skill at https://docs.metronome.com/.well-known/agent-skills/metronome-token-billing/skill.md to monetize this app. ``` After inspecting your repository and any accessible billing state, the agent presents one concise setup checkpoint covering the inferred integration, required decisions, and credentials. Once you confirm it, the agent builds and verifies the integration. To install the skill for repeated use in a supported coding agent, run: ```bash theme={null} npx --yes skills add https://docs.metronome.com --skill metronome-token-billing --yes ``` ## Use case Fictional company Designr is an AI-powered design tool. Customers use Designr to generate design assets, including prototypes, mockups, and images. Designr uses common AI models and charges customers a 10% markup on underlying model costs. Designr offers several plan tiers. Its Pro Plan includes 200 Designr Credits -- a custom pricing unit -- each month. If a customer uses all of their Designr Credits, they can purchase additional credits during the month. ## Set up your rate card In Metronome, a rate card is your centralized price book, where you define pricing for all products. When you use Token Billing, Metronome automatically creates billable metrics, products, and rates for managed AI products based on the markup you enter. You do not need to create these separately. Because Designr uses a custom pricing unit, Designr Credits, first navigate to **Offering > Pricing Units > Custom Pricing Units**. Click **+ Add**, then create a custom pricing unit named **Designr Credits**. Next, create your rate card. > **Note:** When using Token Billing, non-USD fiat currencies are not supported, as provider prices are denominated in USD. ### Create your rate card 1. Click **Offering** in the left-hand sidebar. 2. Navigate to the **Rate Cards** tab and select **+ Add**. 3. Enter the rate card name and description, then enable **Charge based on AI provider pricing (managed)**. You can also add a human-readable alias, such as `default_rate_card`, to reference the rate card more easily throughout the API. 4. Select the AI models you want to use. You can select all models from a provider or expand the provider to select individual models. 5. Add any other usage-based, subscription, or composite products that you want to include on the same rate card. 6. Click **Next** to proceed to the next page. #### Set rates — Custom Pricing Unit 1. Under **Default markup for future AI models**, enter the markup percentage that should automatically apply when new models are added to the rate card. 2. In the upper-right corner of the AI models section, select **USD**. In the dropdown, select the **Designr Credits** custom pricing unit. 3. In the modal, define a conversion rate between USD and Designr Credits. 4. Expand each model to verify its distinct rates by author, provider, and token type. 5. Click **Save**. #### Set rates — USD 1. Under **Default markup for future AI models**, enter the markup percentage that should automatically apply when new models are added to the rate card. 2. Enter markup percentages for each selected model, or use **Apply markup to all** in the upper-right corner to apply the same markup percentage to every selected model. 3. Expand each model to verify its distinct rates by author, provider, and token type. 4. Click **Save**. ## Define your pricing model Because Designr’s Pro Plan includes an allocation of 200 Designr Credits per month, you can create a Package to encode the credit allocation alongside the rate card you just created. In Metronome, [Packages](/guides/implement-metronome/core-concepts/packages-overview) define customer-facing offerings, such as Pro Plan or Max Plan, and simplify assigning PLG customers to these offerings. ## Provision customers You are now ready to assign customers to the Pro Plan. Provisioning a customer with a package creates a contract: a customer-specific agreement that applies the terms from the package. Use the API call below to provision a customer with the Pro Plan: ```bash cURL theme={null} curl --request POST \ --url https://api.metronome.com/v1/contracts/create \ --header "Authorization: Bearer $METRONOME_API_TOKEN" \ --header "Content-Type: application/json" \ --data '{ "customer_id": "13117714-3f05-48e5-a6e9-a66093f13b4d", "package_alias": "designr_pro", "starting_at": "2026-08-28T00:00:00.000Z" }' ``` ```python Python theme={null} response = client.v1.contracts.create( customer_id="13117714-3f05-48e5-a6e9-a66093f13b4d", package_alias="designr_pro", starting_at="2026-08-28T00:00:00.000Z" ) ``` ```javascript Node theme={null} await client.v1.contracts.create({ customer_id: '13117714-3f05-48e5-a6e9-a66093f13b4d', package_alias: 'designr_pro', starting_at: '2026-08-28T00:00:00.000Z' }); ``` ```ruby Ruby theme={null} response = client.v1.contracts.create( customer_id: '13117714-3f05-48e5-a6e9-a66093f13b4d', package_alias: 'designr_pro', starting_at: '2026-08-28T00:00:00.000Z' ) ``` ```go Go theme={null} contractStartingTime, err := time.Parse(time.RFC3339Nano, "2026-08-28T00:00:00.000Z") if err != nil { panic(err.Error()) } contractResponse, err := client.V1.Contracts.New(context.TODO(), metronome.ContractNewParams{ CustomerID: metronome.F("13117714-3f05-48e5-a6e9-a66093f13b4d"), PackageAlias: metronome.F("designr_pro"), StartingAt: metronome.F(contractStartingTime), }) if err != nil { panic(err.Error()) } ``` You can layer on or customize additional terms on this contract. For example, if a customer has exhausted all of their credits for the month and wants to purchase more, you can use Metronome’s [payment-gated credit flow](/guides/pricing-packaging/billing-model-guides/prepaid-credits) to charge for incremental Designr Credits. You can also use [overrides](/guides/pricing-packaging/make-pricing-changes/edit-or-override-a-contract) to customize rates on a per-customer basis. ## Integrate usage tracking Ensure that your events follow the format below, with `event_type` set to `token-billing`. ```bash cURL theme={null} curl --request POST \ --url https://api.metronome.com/v1/ingest \ --header "Authorization: Bearer $METRONOME_API_TOKEN" \ --header "Content-Type: application/json" \ --data '[{ "transaction_id": "b1d52889-f8f7-4aee-a41f-f2eb89789ece", "timestamp": "2026-08-24T18:38:50.597Z", "customer_id": "13117714-3f05-48e5-a6e9-a66093f13b4d", "event_type": "token-billing", "properties": { "model": "anthropic/claude-fable-5", "provider": "anthropic", "input_tokens": 233, "cached_input_tokens": 1459, "output_tokens": 83, "cached_write_tokens": 210 } }]' ``` ```python Python theme={null} response = client.v1.usage.ingest( usage=[ { "transaction_id": "b1d52889-f8f7-4aee-a41f-f2eb89789ece", "timestamp": "2026-08-24T18:38:50.597Z", "customer_id": "13117714-3f05-48e5-a6e9-a66093f13b4d", "event_type": "token-billing", "properties": { "model": "anthropic/claude-fable-5", "provider": "anthropic", "input_tokens": 233, "cached_input_tokens": 1459, "output_tokens": 83, "cached_write_tokens": 210 } } ] ) ``` ```javascript Node theme={null} async function main() { await client.v1.usage.ingest({ usage: [{ transaction_id: 'b1d52889-f8f7-4aee-a41f-f2eb89789ece', timestamp: '2026-08-24T18:38:50.597Z', customer_id: '13117714-3f05-48e5-a6e9-a66093f13b4d', event_type: 'token-billing', properties: { model: 'anthropic/claude-fable-5', provider: 'anthropic', input_tokens: 233, cached_input_tokens: 1459, output_tokens: 83, cached_write_tokens: 210 } }], }); } main(); ``` ```ruby Ruby theme={null} result = metronome.v1.usage.ingest( usage: [ { transaction_id: 'b1d52889-f8f7-4aee-a41f-f2eb89789ece', timestamp: '2026-08-24T18:38:50.597Z', customer_id: '13117714-3f05-48e5-a6e9-a66093f13b4d', event_type: 'token-billing', properties: { model: 'anthropic/claude-fable-5', provider: 'anthropic', input_tokens: 233, cached_input_tokens: 1459, output_tokens: 83, cached_write_tokens: 210 } } ] ) puts(result) ``` ```go Go theme={null} err := client.V1.Usage.Ingest(context.TODO(), metronome.UsageIngestParams{ Usage: []metronome.UsageIngestParamsUsage{{ TransactionID: metronome.F("b1d52889-f8f7-4aee-a41f-f2eb89789ece"), Timestamp: metronome.F("2026-08-24T18:38:50.597Z"), CustomerID: metronome.F("13117714-3f05-48e5-a6e9-a66093f13b4d"), EventType: metronome.F("token-billing"), Properties: metronome.F(map[string]interface{}{ "model": "anthropic/claude-fable-5", "provider": "anthropic", "input_tokens": 233, "cached_input_tokens": 1459, "output_tokens": 83, "cached_write_tokens": 210, }), }}, }) if err != nil { panic(err.Error()) } ``` The token usage fields track the number of tokens consumed by type: * `input_tokens`: Tokens in the prompt * `cached_input_tokens`: Cached prompt tokens * `output_tokens`: Tokens in the response * `cached_write_tokens`: Cache-write tokens. Supported for Anthropic models and OpenAI GPT-5.6+ models only The `model` and `provider` fields match each token count to the correct rate. Send events in the correct format to Metronome’s `/ingest` endpoint. Then navigate to the **Events** page to confirm that the events have matched a billable metric. ## Token price updates When model providers release new models, Metronome automatically updates your rate card to include those models at the default markup specified on the rate card. When a model provider changes a token price, Metronome automatically updates the price on your rate card while preserving the markup configured on the rate card. # Edit a contract Source: https://docs.metronome.com/guides/pricing-packaging/make-pricing-changes/edit-contract The ability to edit a contract helps you react quickly to the needs of your customers and your business. When a customer's contract needs updating to reflect a mid-term up-sell or to correct an error, you can edit terms on a contract through the Metronome UI or through the API with the `editContract` endpoint. When you edit a contract, any draft invoices update immediately to reflect that edit. Finalized invoices remain unchanged. If you void and regenerate a finalized invoice, the regenerated invoice updates to reflect the edits you made. ## Contract editing examples This section describes example contract editing scenarios for a company named BigData. ### Edit the access schedule and invoice schedule for a commit In this example, BigData’s customer initially negotiated a 2-year SLG contract with a \$100K prepaid commit applicable for the first year. The contract started on January 1, 2025 and spans until January 1, 2027. After only 6 months, they’ve used the product very quickly and only have \$10K left on their commit. They reach out and negotiate new terms. They’ve doubled their commit amount to \$200K, but now have the full 2-year contract term to consume \$200K. To implement this change in Metronome, BigData: * Increases the amount of the access schedule segment to \$200K * Extends the `ending_before` date to the end of the contract term * Adds another invoice schedule segment to charge the customer now for the additional \$100K commit This example API call shows the described contract edit: ```bash theme={null} curl https://api.metronome.com/v2/contracts/edit \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "customer_id": "13117714-3f05-48e5-a6e9-a66093f13b4d", "contract_id": "d7abd0cd-4ae9-4db7-8676-e986a4ebd8dc", "update_commits": [ { "commit_id": "2e30f074-d04c-412e-a134-851ebfa5ceb2", "access_schedule": { "update_schedule_items": [ { "id": "d38a8230-3614-46f9-82c6-82e53ac630d6", "amount": 20000000, "ending_before": "2027-01-01T00:00:00.000Z" } ] }, "invoice_schedule": { "add_schedule_items": [ { "timestamp": "2025-07-01T00:00:00.000Z", "amount": 10000000 } ] } } ] }' ``` ### Edit the applicable product IDs for a commit In this example, a customer’s contract includes a product-specific prepaid commitment named Commit A. Only the usage of the Data Reads product is eligible to consume their commitment. The finalized February 2025 invoice includes usage of Data Reads and Data Writes products. Only Data Reads consumes the prepaid commitment. | Product | Applied commit or credit | Price | Quantity | Total | | :---------- | :----------------------- | :---- | :------- | :---- | | Data Reads | Commit A | \$10 | 10 | \$100 | | Data Writes | | \$5 | 10 | \$50 | | | | | Total | \$50 | The draft March 2025 invoice also includes usage of Data Reads and Data Writes. Again, only Data Reads consumes the prepaid commitment. | Product | Applied commit or credit | Price | Quantity | Total | | :---------- | :----------------------- | :---- | :------- | :---- | | Data Reads | Commit A | \$10 | 3 | \$30 | | Data Writes | | \$5 | 2 | \$10 | | | | | Total | \$10 | The customer then negotiates a mid-term change to their contract, where Data Writes is now eligible to burn down these commits, starting with the March 2025 billing period. This example API call from March 5, 2025 edits the applicable product IDs associated with the commitment to add Data Reads and Writes. ```bash theme={null} curl https://api.metronome.com/v2/contracts/edit \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "customer_id": "40f388e0-3fa8-4b4f-b4c8-b5a7a97fdb48", "contract_id": "323cdf39-678a-49b8-a6ce-5c4b1e108b9c", "update_commits": [ { "commit_id": "d0d1472b-e63a-46d2-b9cb-036cd57db7e6", "applicable_product_ids": [ "f3a30bcb-e35a-4409-b20b-45b33efc459d", "4ef215cd-0bee-4518-93c9-4caf76cb3db9" ] } ] }' ``` The draft March 2025 invoice immediately reflects the change to the applicable product IDs. For the whole billing period, Commit A can now draw down both Data Reads and Data Writes. | Product | Applied commit or credit | Price | Quantity | Total | | :---------- | :----------------------- | :---- | :------- | :---- | | Data Reads | Commit A | \$10 | 3 | \$30 | | Data Writes | Commit A | \$5 | 2 | \$10 | | | | | Total | \$0 | The finalized February 2025 invoice remains untouched. | Product | Applied commit or credit | Price | Quantity | Total | | :---------- | :----------------------- | :---- | :------- | :---- | | Data Reads | Commit A | \$10 | 10 | \$100 | | Data Writes | | \$5 | 10 | \$50 | | | | | Total | \$50 | If the client had voided and regenerated the month 1 invoice, Commit A would apply to both Data Reads and Data Writes, based on the current state of the contract. ## Track edits over time View a contract’s history to track all changes and edits made over time. The `getEditHistory` endpoint returns all edits ever made to a contract. This includes any edits made through: * The `editContract` endpoint * The `updateEndDate` API endpoint * Adding usage filters with the `setUsageFilters` endpoint * The Metronome UI Here’s an example response from getEditHistory. This response shows that the contract was edited twice: once to add an override and once to add a commit. ```json theme={null} { "data": [ { "add_overrides": [ { "applicable_product_tags": [], "id": "80c8e124-a4fb-4264-b2e6-ac2479d075dc", "is_commit_specific": false, "multiplier": 0.5, "override_specifiers": [ { "product_id": "90c47b63-8095-4369-9779-c65cc4fe3af7" } ], "product": { "id": "90c47b63-8095-4369-9779-c65cc4fe3af7", "name": "Reads" }, "starting_at": "2025-02-01T00:00:00+00:00", "type": "MULTIPLIER" } ], "id": "a19c750a-ffe4-57ae-9645-cb8682904afb", "timestamp": "2025-02-26T23:07:00.727000+00:00" }, { "add_commits": [ { "access_schedule": { "credit_type": { "id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "name": "USD (cents)" }, "schedule_items": [ { "amount": 10000, "ending_before": "2025-03-01T00:00:00+00:00", "id": "11980e47-96b5-4527-bb38-149edc205c34", "starting_at": "2025-02-01T00:00:00+00:00" } ] }, "id": "e647c959-9eeb-49d2-ac21-2f2141e3e1fd", "invoice_schedule": { "credit_type": { "id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "name": "USD (cents)" }, "schedule_items": [ { "amount": 10000, "id": "c5cb2f25-fa4e-4ff6-9cdd-ff5edfe73acc", "invoice_id": "0ce97fbd-d19f-52c8-80d6-4b877ad31177", "quantity": 1, "timestamp": "2025-02-01T00:00:00+00:00", "unit_price": 10000 } ] }, "priority": 100, "product": { "id": "35a467c7-fc24-46c2-884b-66af8d349674", "name": "Support" }, "rate_type": "LIST_RATE", "type": "PREPAID" } ], "id": "0551864c-edc7-5045-bcec-3688b4d53c3f", "timestamp": "2025-02-26T23:07:16.031000+00:00" } ] } ``` To view the full state of a contract at any historical point, use the `as_of_date` parameter on the `getContract` endpoint. This example response shows the full state of the contract after the first edit but before the second edit. It takes the `created_at` time for the first edit and passes that into the `as_of_date` parameter in `getContract`. ```json theme={null} { "data": { "commits": [], "created_at": "2025-02-26T23:06:32.574000+00:00", "created_by": "User", "credits": [], "custom_fields": {}, "customer_id": "d0d1472b-e63a-46d2-b9cb-036cd57db7e6", "id": "c5e8d83b-23e7-4747-a5fe-8a33f4404fe1", "multiplier_override_prioritization": "LOWEST_MULTIPLIER", "name": "test rate card", "overrides": [ { "applicable_product_tags": [], "id": "80c8e124-a4fb-4264-b2e6-ac2479d075dc", "is_commit_specific": false, "multiplier": 0.5, "override_specifiers": [ { "product_id": "90c47b63-8095-4369-9779-c65cc4fe3af7" } ], "product": { "id": "90c47b63-8095-4369-9779-c65cc4fe3af7", "name": "Reads" }, "starting_at": "2025-02-01T00:00:00+00:00", "type": "MULTIPLIER" } ], "rate_card_id": "c38bc471-0c45-41d1-b802-0bae4554e771", "recurring_commits": [], "recurring_credits": [], "scheduled_charges": [], "starting_at": "2025-02-01T00:00:00+00:00", "transitions": [], "usage_filter": [], "usage_statement_schedule": { "billing_anchor_date": "2025-02-01T00:00:00+00:00", "frequency": "MONTHLY" } } } ``` **TIP** All edits to a contract are also recorded in the Metronome audit logs, available in the Metronome UI and through the API. ## Supported Edits Currently, the following edits are supported: * Adding new commits * Editing Commit access and invoice schedules * Editing Commit name and description * Editing Applicable product IDs and Applicable product tags on commits * Editing Rollover fraction on commits * Archiving commits * Adding new recurring commits * Editing ending\_before, the invoice amount, and the access amount on recurring commits * Adding new credits * Editing credit access schedules * Editing Credit name and description * Editing Applicable product IDs and Applicable product tags on credits * Adding new recurring credits * Archiving credits * Editing ending\_before and the access amount on recurring credits * Adding new overrides * Removing overrides * Adding new scheduled charges * Editing scheduled charge invoice schedules * Archiving scheduled charges * Adding spend threshold configuration * Updating spend threshold configuration * Updating contract end date * Updating contract name ## Limitations The contract editing feature has these guardrails. **Commit and scheduled charge invoice schedules** * If the invoice schedule item is associated with a *finalized invoice* , you cannot remove or update the invoice schedule item. * If the invoice schedule item is associated with a *voided invoice* , you cannot remove the invoice schedule item. **Commit and credit access schedules** * You cannot remove an access schedule segment that was applied to a finalized invoice. You can void the invoice beforehand *and then* remove the access schedule segment. * If you remove an access schedule segment, its manual ledger entry is also removed. * If you change the access schedule of a commit or credit, any draft invoices reflects the change in access schedule immediately. Finalized invoices remain untouched. If you void and regenerate the finalized invoices, the regenerated invoices reflect the new access schedule of the credit or commit. **Rollover commits** * You cannot edit rollover commits. * You can edit the access schedule of the originating commit until the contract it was transitioned to has a finalized invoice. * You can edit the invoice schedule of the originating commit until the original contract has ended. **Finalized scheduled invoices** Consider a scenario where you add a new invoice schedule item on timestamp X, or edit the timestamp for an invoice schedule item to date X. In the case where there’s already a finalized scheduled invoice for that timestamp, that finalized scheduled invoice remains untouched. Metronome creates a new finalized scheduled invoice for the edited invoice schedule items. **Archiving terms** * Before archiving a commit, all finalized usage invoices that the commit was applied to must be voided. Any finalized invoices for commit payment must also be voided. * Before archiving a credit, all finalized usage invoices that the credit was applied to must be voided. * Before archiving a scheduled charge, all finalized invoices created by the scheduled charge must be voided. # Contract edits and overrides Source: https://docs.metronome.com/guides/pricing-packaging/make-pricing-changes/edit-or-override-a-contract Metronome [rate cards](/guides/get-started/core-concepts/create-manage-rate-cards) contain default rates and entitlement states for your customers, or a subset of your customers. Individual customers can negotiate custom discounts when signing a contract, or you may want to grant time-based promotions to a cohort of customers. To enable these use cases in Metronome, use contract-level overrides. ## Override types​ Use overrides with usage, subscription, and composite products to override the rate or entitlement of a product. There are three types of rate overrides: * **Multiplier** multiplies the rate on the rate card by the specified number. For example, a 0.9 multiplier gives a 10% discount from the list rate. As the list rate on the rate card changes, the effective rate after the multiplier is applied also changes. * **Overwrite** sets a flat or tiered rate for the product. For example, an overwrite can specify that a product’s price is \$3.23. The price for that product remains at \$3.23 regardless of changes to the list price on the rate card. * **Tiered** multiplies the rate on the rate card by the specified number, for a given quantity range. For example, specify a 0.9 multiplier with `size = 5` to give a 10% discount from the list rate only on the first 5 uses in the billing period. **INFO** You can only use tiered overrides when the contract uses explicit override prioritization. You can also override the entitlement for any product. For example, if a given product is disabled on the rate card but a customer has early access to the product, add an override to enable the product on the customer’s rate card. Once a product's entitlement is enabled, usage of that product appears on the customer’s invoices. ## Target overrides​ To fine-tune what overrides apply to, target them to specific product IDs, product tags, or pricing and presentation group values. For most cases, use the `applicable_product_tags` and `product_id` fields in the API or UI. Any product that has a product tag included in the `applicable_product_tags` array, or with the specified product ID is targeted for the override. If you need more complex logic, use the `override_specifiers` field in the API to target overrides based on combinations of product ID, product tags, and pricing and presentation group values. The `override_specifiers` field takes in an array of objects, where each object is called a specifier. Within each specifier all fields are ANDed together. If the conditions of any specifier in the array are met, then the line item is targeted for the override. For example, this `override_specifiers` field targets a multiplier against any usage that meets either of these requirements: * The product has the product tags `Read` and `Write` and a pricing group value of `resource.region = af-south-1` * The product has the product tag `Query` and the pricing group values `resource.region = uaenorth` and `resource.hardware = gpu1` ```bash theme={null} curl https://api.metronome.com/v1/contracts/create \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "e15ce0e6-33f0-44bb-89c7-05bc296f5b5e", "contract_id": "f9e0b117-42e0-4145-b524-b97302a57518", "starting_at": "2024-01-01T00:00:00.000Z", "overrides": [ { "starting_at": "2024-01-01T00:00:00.000Z", "type": "multiplier", "multiplier": 0.7, "priority":1, "override_specifiers": [ { "product_tags": ["Read", "Write"], "pricing_group_values": { "resource.region": "af-south-1" } }, { "product_tags": ["Query"], "pricing_group_values": { "resource.region": "uaenorth", "resource.hardware":"gpu1" } } ] } ] }' ``` **INFO** You cannot use product tags to target overwrite overrides. When using dimensional pricing, you must use the product ID with or without pricing group values and specify all pricing group values to apply the override. For example, if the rate is specifically for the `us-east1` region and `gpu1` hardware type, you must specify the product ID and both pricing group values in the `override_specifiers`. ## Example: Time-based discount against a product tag​ To create time-based discounts, specify `starting_at` and `ending_before` dates on the override. Beyond that, using product tags to target overrides makes launching new products easier. Add the pertinent product tags to a new product on creation, and any discounts automatically apply. This API call grants a 30% discount on all products that have either the product tag `Read` or `Write` for all of 2024. This example has simple targeting logic, so it uses the `applicable_product_tags` field. To target products that have both `Read` and `Write` product tags, you would use the `override_specifiers` field instead. ```bash theme={null} curl https://api.metronome.com/v1/contracts/create \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "e15ce0e6-33f0-44bb-89c7-05bc296f5b5e", "contract_id": "f9e0b117-42e0-4145-b524-b97302a57518", "starting_at": "2024-01-01T00:00:00.000Z", "overrides": [ { "starting_at": "2024-01-01T00:00:00.000Z", "ending_before": "2025-01-01T00:00:00.000Z", "type": "multiplier", "multiplier": 0.7, "priority":1, "applicable_product_tags":["Read", "Write"] } ] }' ``` ## Example: Discount on dimensional pricing​ When using [dimensional pricing](/guides/get-started/core-concepts/create-manage-rate-cards#dimensional-pricing%E2%80%8B), you may want to grant a discount on a subset of rates associated with one product without granting a discount on all rates. For example, a customer may know that they only use resources in regions `af-south-1` and `uaenorth`. So, they negotiate a discount for the usage of your product only in those two regions. If they use resources in other regions, they get charged at the list rate. This API call grants a discount on rates associated with usage in specific regions. ```bash theme={null} curl https://api.metronome.com/v1/contracts/create \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "e15ce0e6-33f0-44bb-89c7-05bc296f5b5e", "contract_id": "f9e0b117-42e0-4145-b524-b97302a57518", "starting_at": "2024-01-01T00:00:00.000Z", "overrides": [ { "starting_at": "2024-01-01T00:00:00.000Z", "type": "multiplier", "multiplier": 0.7, "priority":1, "override_specifiers": [ { "product_id": "329e6313-ecda-4548-bb71-750ecc2af11a", "pricing_group_values": { "resource.region": "af-south-1" } }, { "product_id": "329e6313-ecda-4548-bb71-750ecc2af11a", "pricing_group_values": { "resource.region": "uaenorth" } } ] } ] }' ``` Pricing group values specified in the override can be a subset of all the pricing group values associated with a product. For example, imagine that the product has two pricing group keys, `resource.region` and `resource.hardware`. Adding the above override ensures that usage within `af-south-1` and `uaenorth` receive a 30% discount, regardless of the hardware type. ## Example: Discount against usage for a specific cluster ID​ Some clients have a business model where they grant customers discounts for using specific resources, like bring-your-own-model pricing. These resources aren’t set as pricing group keys to allow distinct pricing across all customers. Instead, they’re set as presentation group keys. This API call grants 20% off of a product when using a specific `cluster_id` and `resource_id` combination. ```bash theme={null} curl https://api.metronome.com/v1/contracts/create \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "e15ce0e6-33f0-44bb-89c7-05bc296f5b5e", "contract_id": "f9e0b117-42e0-4145-b524-b97302a57518", "starting_at": "2024-01-01T00:00:00.000Z", "overrides": [ { "starting_at": "2024-01-01T00:00:00.000Z", "type": "multiplier", "multiplier": 0.8, "priority":1, "override_specifiers": [ { "product_id": "329e6313-ecda-4548-bb71-750ecc2af11a", "presentation_group_values": { "cluster_id":"43145", "resource_id":"5436436" } } ] } ] }' ``` ## Example: Discount based on quantity consumed​ Use tiered overrides to incentivize usage and give a customer discounts based on the quantity they consume. This API call grants a 20% discount on list prices for the first 10 uses of a product in the billing period, and a deeper discount of 30% for the next 10 uses. ```bash theme={null} curl https://api.metronome.com/v1/contracts/create \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "e15ce0e6-33f0-44bb-89c7-05bc296f5b5e", "contract_id": "f9e0b117-42e0-4145-b524-b97302a57518", "starting_at": "2025-01-01T00:00:00.000Z", "overrides": [ { "starting_at": "2024-01-01T00:00:00.000Z", "type": "tiered", "priority":1, "product_id": "2fc7d449-2e30-4d7d-accb-37835722a313", "tiers": [ { "size":10, "multiplier":0.8 }, { "size":10, "multiplier":0.7 } ] } ] }' ``` ## Override prioritization​ For a given line item on a usage invoice, only one override is prioritized. Overrides don't stack. Overwrite overrides have the highest priority and always take precedence over multiplier or tiered overrides. In the case of multiple applicable overwrite overrides, the last-added overwrite override applies. Specify how to prioritize multiplier overrides when creating the contract. * **Lowest multiplier** : The applicable multiplier that grants the largest discount is applied. * **Explicit** : Specify a priority on each multiplier override. The override with the lowest priority value is prioritized. # Launch new pricing​ Source: https://docs.metronome.com/guides/pricing-packaging/make-pricing-changes/make-a-pricing-change In traditional billing systems, preparing for a new product or pricing launch can require significant cross-functional coordination and months of work to ensure the change takes place at the right moment for the right customers. Metronome’s unique model streamlines this process by allowing you to schedule changes for a specified time period, with the ability to flexibly introduce new pricing across all customers, specific cohorts, or to individual customers, depending on your needs. ## Make a pricing change for all customers Use the rate card to easily introduce new products or schedule rate changes for all customers. ### Schedule a rate change To introduce a new product or schedule a rate change for all customers through the API, make a POST request to `/contract-pricing/rate-cards/addRates`. This is the same endpoint used to create new rates. Imagine you are launching a new product to all customers, and you know that you will need to increase prices after a year. The example below showcases how you can use Metronome to easily add a new product and schedule a pricing change in a year, in a single API call. This allows you to make pricing changes across all your customers in advance, so your teams can focus on your customers rather than on billing. ```bash theme={null} curl https://api.metronome.com/v1/contract-pricing/rate-cards/addRates \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "rate_card_id": "d7abd0cd-4ae9-4db7-8676-e986a4ebd8dc", "rates": [ { "product_id": "13117714-3f05-48e5-a6e9-a66093f13b4d", "starting_at": "2024-01-01T00:00:00.000Z", "entitled": true, "rate_type": "FLAT", "price": 100, "pricing_group_values": { "region": "us-west-2", "cloud": "aws" } }, { "product_id": "13117714-3f05-48e5-a6e9-a66093f13b4d", "starting_at": "2024-01-01T00:00:00.000Z", "entitled": true, "rate_type": "FLAT", "price": 120, "pricing_group_values": { "region": "us-east-2", "cloud": "aws" } } ] }' ``` ## Make a pricing change for specific cohorts Use [packages](https://docs.metronome.com/guides/get-started/core-concepts/packages-overview) to easily introduce new pricing to specific cohorts of new customers. This is especially useful in scenarios where you are rolling out consistently defined pricing packages for new customers and want existing customers to maintain grandfathered prices. ### Grandfather in existing customers Imagine that instead of launching to all customers, you want to launch your new product for new customers only. Legacy customers can opt in to the new product as needed. To do this, you can add the new product to the rate card but default the entitlement to `false`. ```bash theme={null} curl https://api.metronome.com/v1/contract-pricing/rate-cards/addRates \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "rate_card_id": "d7abd0cd-4ae9-4db7-8676-e986a4ebd8dc", "rates": [ { "product_id": "13117714-3f05-48e5-a6e9-a66093f13b4d", "starting_at": "2024-01-01T00:00:00.000Z", "entitled": false, "rate_type": "FLAT", "price": 100, "pricing_group_values": { "region": "us-west-2", "cloud": "aws" } } ] }' ``` Create a package with the default rates for new customers with the new product entitled: ```bash theme={null} curl \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "name": "2024 Compute Pricing", "rate_card_id": "d7abd0cd-4ae9-4db7-8676-e986a4ebd8dc", "aliases": [{ "name": "New Customer Pricing", "starting_at": "2024-01-01T00:00:00.000Z" }], "net_payment_terms_days": 15, "duration": { "value": 12, "unit": "MONTHS" }, "overrides": [{ "starting_offset": { "value": 0, "unit": "MONTHS" }, "override_specifiers": [{ "product_id": "13117714-3f05-48e5-a6e9-a66093f13b4d", "pricing_group_values": { "region": "us-west-2", "cloud": "aws" } }], "entitled": true }] }' ``` Provision your customers with the '/contracts/create' endpoint: ```bash theme={null} curl https://api.metronome.com/v1/contracts/create \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "aa58107d-162f-407e-9f09-940f16adbb1c", "starting_at": "2025-10-01T00:00:00.000Z", "package_alias": "New Customer Pricing" }' ``` New customers will be provisioned with the new product while existing customers see no change to their contracted pricing. **INFO** Package rates are applied on top of rate card changes. Customers provisioned on a package with a rate card will still inherit most pricing changes made to the rate card. This enables flexibility in being able to launch pricing changes both at the rate card level for all customers, and at the package level for specific cohorts. The only exception is if the package contains an overwrite override, in which case [standard override rules](https://docs.metronome.com/guides/pricing-packaging/make-pricing-changes/edit-or-override-a-contract#override-types​) apply. ### Make pricing changes easy with package aliases Use package aliases to future-proof pricing changes without updating your provisioning infrastructure. For example, imagine you want to update the price of your new compute product in a year and want to continue grandfathering existing clients to their original price. To do this, you can create a new package with the same alias: ```bash theme={null} curl \\ -H "Authorization: Bearer " \\ -H "Content-Type: application/json" \\ -d '{ "name": "2025 Compute Pricing", "rate_card_id": "d7abd0cd-4ae9-4db7-8676-e986a4ebd8dc", "aliases": [ { "name": "New Customer Pricing", "starting_at": "2025-01-01T00:00:00.000Z" } ], "net_payment_terms_days": 15, "duration": { "value": 12, "unit": "MONTHS" }, "overrides": [ { "starting_offset": { "value": 0, "unit": "MONTHS" }, "override_specifiers": [ { "product_id": "13117714-3f05-48e5-a6e9-a66093f13b4d", "pricing_group_values": { "region": "us-west-2", "cloud": "aws" } } ], "type": "OVERWRITE", "overwrite_rate": { "rate_type": "FLAT", "price": 120 } } ] }' ``` The “New Customer Pricing” package now points to the newly created package with an increase in price from \$1 → \$1.20. The original package will automatically show an alias schedule of “New Customer Pricing” from Jan. 1, 2024 - Jan 1, 2025. New customers will automatically be provisioned on the updated package starting on Jan. 1, 2025 without any need to change the above provisioning flow, since Metronome manages the transition of aliases across packages. ## Make a pricing change for individual customers If any of your grandfathered customers want to migrate to the new package, you can either end their contract and re-provision their contract with the new pricing, or edit the contract directly to make changes scoped individually. In many cases, individual customers may negotiate specific pricing changes that you will want to reflect separately from your standard rate card or package. Metronome’s contract flexibility allows you to introduce custom overrides to contracts to enable individually-scoped changes. See the following page on [contract editing](https://docs.metronome.com/guides/pricing-packaging/make-pricing-changes/edit-or-override-a-contract) for more details. # Set currencies and custom pricing units Source: https://docs.metronome.com/guides/pricing-packaging/make-pricing-changes/use-currency-custompricingunits You can create custom pricing units and use different currencies when building a rate card in Metronome. Doing so ensures that billing aligns with the unique needs of your products and services, no matter where your customers are located. Pricing using custom units can decouple pricing from currency fluctuations and provide a standardized unit of value that's understandable across all markets. This approach simplifies pricing logic for customers to understand how their usage translates into cost. ## Supported currencies​ Use different currencies to provide a localized billing experience for your global customers. Metering on local currency eliminates confusion around conversion rates and provides a customer-centric billing approach for international customers. Metronome supports these currencies: | USD | AUD | BRL | CAD | | --- | --- | --- | --- | | CHF | CZK | EUR | GBP | | INR | MXN | NGN | NOK | | PLN | SEK | TRY | ZAR | | NZD | SGD | DKK | CNY | ### Currency denomination All monetary values in the Metronome API are expressed in the **smallest denomination** (minor unit) of the currency. For USD, this means values are in **cents** — so \$1.00 is represented as `100`. This applies to all API fields that represent monetary amounts, including `total`, `unit_price`, `amount`, and `threshold`. **USD uses cents, but most other currencies use whole units** USD is the only currency in Metronome that uses cents (minor units) by default. All other supported fiat currencies — such as EUR, GBP, and CAD — use **whole currency units**. For example, €10.00 EUR is represented as `10`, not `1000`. When working with multiple currencies, make sure your integration accounts for this difference. Do not assume that dividing by 100 applies to all currencies. The denomination for each currency is reflected in the pricing unit name returned by the API. For example, USD returns as `"USD (cents)"`, indicating values are in cents. Other currencies return their standard code (for example, `"EUR"`) without a denomination qualifier, indicating values are in whole units. ## Use custom pricing units​ To use custom pricing units: 1. Create a custom pricing unit in the [Metronome app](https://app.metronome.com/). * Go to **Offering → Pricing units → Custom pricing units →** and click **Add**. * Name your new pricing unit as you want it to appear on Metronome invoices. 2. [Create a rate card](/guides/get-started/core-concepts/create-manage-rate-cards) and set the rate card’s fiat currency. Each rate card is associated with one fiat currency. * Add rates to the rate card in either the chosen fiat currency or custom pricing units. * If the rate is a custom pricing unit, define a conversion rate from the underlying fiat currency. **NOTE** Once the rate is saved in one pricing unit for a given product, you cannot change the pricing unit for that rate afterwards. Rate card CPU example 3. Click **Save**. ## Example: Use custom pricing units and currencies in commits or credits​ Credits and prepaid commits, on a contract or at the customer level, can have access schedules in custom pricing units and select currencies. For example, you can have a prepaid commit, paid for in CHF, that gives access to 100 Cloud Compute Tokens. Commit CPU example ## Example: Invoice with custom pricing units and currencies​ Usage of a product with custom pricing unit rates burns down credits and prepaid commits with access schedules in that custom pricing unit. For example, 100 Cloud Compute Tokens was burned down by the AI Model Training usage. If there are no applicable credits or prepaid commits with access schedules in that custom pricing unit, a conversion line item is added to calculate the cost in the specified fiat currency set on the rate card. For Acme’s invoice, after burning down all prepaid commits, the remaining total of 350 Cloud Compute tokens is converted to the fiat currency and is the total due. Invoice CPU example # Overview Source: https://docs.metronome.com/guides/pricing-packaging/overview # Pricing & Packaging Design, implement, and optimize your pricing strategy with Metronome's flexible billing infrastructure. Whether you're launching a new product, scaling an existing business, or adapting to market changes, this section provides comprehensive guides to help you build the right pricing model for your customers. ## What you'll learn This section covers everything from foundational billing models to advanced pricing strategies, including: * **Billing Models**: Implement pay-as-you-go, subscriptions, enterprise commits, and hybrid approaches * **Pricing Changes**: Update rates, schedule price changes, and manage contract modifications * **Credits & Commits**: Apply discounts, create pre-paid commitments, and target specific usage * **Market Examples**: Learn from real-world implementations by industry leaders ## Key topics ### Configure your billing model Choose the right billing approach for your business: * **Pay-as-you-go**: Consumption-based pricing for flexible, scalable products * **Enterprise Commits**: Volume discounts and committed usage for enterprise customers * **Subscriptions with Usage**: Hybrid models combining recurring fees with usage-based components * **Pre-paid Credits**: Credit-based systems for predictable customer spending ### Make pricing changes Adapt your pricing strategy as your business evolves: * **Edit Contracts**: Modify existing customer agreements and pricing terms * **Schedule Changes**: Plan future pricing updates with precise timing control * **Override Pricing**: Apply custom rates for specific customers or use cases * **Currency & Units**: Configure multi-currency support and custom pricing units ### Apply credits and commits Optimize customer relationships with flexible discounting: * **Target Usage**: Apply credits and commits to specific products or usage patterns * **Pre-paid Commits**: Create volume-based commitments with automatic discounting * **Manual Gating**: Control when commitments become active based on payment status * **Prioritization**: Set rules for how different credits and commits are applied ### Recreate market leaders Learn from successful implementations: * **OpenAI**: Usage-based AI API pricing with tiered access * **Anthropic**: Enterprise-grade AI with commitment structures * **Databricks**: Data platform pricing with compute and storage components ## Getting started Ready to implement your pricing strategy? Start with the [billing model guides](/guides/pricing-packaging/billing-model-guides/guides-home) to choose the right approach for your business, or explore [market leader examples](/guides/pricing-packaging/recreate-a-market-leader/company-guides-home) to see how successful companies structure their pricing. # Define subscription pricing Source: https://docs.metronome.com/guides/pricing-packaging/subscription/define-subscription-pricing Create the list prices for your subscription offerings by first creating your subscription products and then adding them to your rate card. ## Create a subscription product​ Create a subscription product in the [Metronome app](https://app.metronome.com/offering/products) or with the API using the [/v1/contract-pricing/products/create](/api-reference/products/create-a-product) end point. Create a subscription product for each type of subscription you offer. For example, if you offer a Good, Better, and Best plan, create a product for each. ## Optionally add seat id as presentation group key for usage products If planning to support a seat based credit model, ensure that all applicable usage products have a `seat_id` presentation group key set on them. This will be used to determine the usage on a per product, per seat basis. See an example of a usage event with a `seat_id` property below: ```json theme={null} { "event_type": "video_generation", "properties": { "model_name": "claude-3-opus", "resolution": "1080p", "environment": "production", "video_duration_seconds": 20, "seat_id": "example@metronome.com" }, "transaction_id": "21f00039-0572-4f63-bf0f-b19faa3d10f8", "customer_id": "94fbf9f3-2826-4503-8446-013c68817744", "timestamp": "2025-10-15T15:23:48.751Z" } ``` ## Add a subscription product to a rate card​ Add your subscription product(s) to a rate card with the [Metronome app](https://app.metronome.com/offering/rate-cards) or the API. Your rate card acts as your list price for your subscription offering based on a quantity of 1. Quantity amount and associated credits are configured later, during the contract creation process. When using the API to [add rates](/api-reference/rate-cards/add-a-rate) to a rate card: 1. Add your subscription to the rate card as a `flat` rate. 2. Specify a `price` and `billing_frequency`. 3. Specify an `entitlement` state. If you have more than one subscription rate on your rate card, Metronome recommends defaulting them to `false` and enabling them when provisioning a contract. This call shows an example of using `rate-cards/addRate` to add subscription products to a rate card: ```json theme={null} { "entitled": false, "product_id": "660445c5-e409-42dc-9aac-07df3b2cde35", "rate_card_id": "a7bc3775-b651-46b6-b7e4-d225a7e55c4c", "rate_type": "flat", "starting_at": "2025-04-01T00:00:00.000Z", "price": 500, "billing_frequency": "MONTHLY" } ``` # Manage seats Source: https://docs.metronome.com/guides/pricing-packaging/subscription/manage-seats Understand how to change the number of seats on a subscription, monitor active balance, and poll history of edits. ## Change seat count Once a contract is created, you can edit the amount of seats on the subscription using the [edit contract end point](/api-reference/contracts/edit-a-contract). The mechanism for changing seat count depends on whether you are using the `quantity` field to adjust count or the `seat_config`. ### Quantity change​ for standard subscriptions and credit pools Schedule a change of the quantity of a subscription using the `update_subscription` action on the [edit contract endpoint](/api-reference/contracts/edit-a-contract). Either pass the new total count through `quantity` or the difference between the previous count through `quantity_delta`. Updates scheduled with the same `starting_at` are applied in the order they are submitted in. Quantity changes are invoiced based on the proration settings in the subscription configuration on the contract. For subscriptions linked to recurring credits, the change in `quantity` will also release new credit balance. The balance amount depends the proration settings and `access_amount` on the recurring credit configuration. This call shows an example of using `/contracts/edit` to change a subscription seat count: ```json theme={null} { "customer_id": "68cd7fb2-235a-4d4d-9ee3-15c49e866884", "contract_id": "7f865c1b-1c08-40e8-9c09-b3238fd3b50d", "update_subscriptions": [ { "subscription_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "quantity_updates": [ { "quantity": 3, "starting_at": "2025-04-29T00:00:00.000Z" } ] } ] } ``` ### Quantity change​ for seat-based credit subscriptions As opposed to just changing the `quantity`, specify the `seat_ids` which are being added or removed from the subscription. Optionally add or remove unassigned seats. Invoices are billed and credits are released based on the settings of the subscription and recurring credits configs. See an example of changing the seat count for seat-based credit subscriptions: ```json theme={null} { "customer_id": "1f79c5c6-400a-4be4-9573-30c667454e4c", "contract_id": "2159a5c1-7436-43eb-a46c-7a2e5f030afa", "update_subscriptions": [ { "subscription_id": "16de7fa0-b387-44e9-b521-0945db3b8af8", "seat_updates": { "add_seat_ids": [ { "seat_ids": ["customer4@metronome.com"], "starting_at": "2025-12-01T00:00:00Z" } ], "remove_seat_ids": [ { "seat_ids": ["customer2@metronome.com"], "starting_at": "2025-11-15T00:00:00Z" } ], "add_unassigned_seats": [ { "quantity": 2, "starting_at": "2025-10-01T00:00:00Z" } ] } } ] } ``` ### Removing a seat ID while maintaining total quantity In certain cases, your customers may change who has access to a seat. As people change roles or leave their company, they may want to free up the seat for someone else to use. To do this in Metronome, remove the seat ID and add an unassigned seat. This ensures that the total quantity for the subscription stays the same, but that a seat is now available for someone else to use. This example removes a seat ID and adds an unassigned in the same call: ```json theme={null} { "customer_id": "1f79c5c6-400a-4be4-9573-30c667454e4c", "contract_id": "2159a5c1-7436-43eb-a46c-7a2e5f030afa", "update_subscriptions": [ { "subscription_id": "16de7fa0-b387-44e9-b521-0945db3b8af8", "seat_updates": { "remove_seat_ids": [ { "seat_ids": ["customer1@metronome.com"], "starting_at": "2025-11-15T00:00:00Z" } ], "add_unassigned_seats": [ { "quantity": 1, "starting_at": "2025-11-15T00:00:00Z" } ] } } ] } ``` ## Monitor credit balance You can set [threshold notifications](/guides/customers-billing/set-up-notifications/create-and-manage-notifications) on credit balance to receive webhooks when the customer's balance reaches a certain level. Upon receiving these webhooks, you can gate the customer’s access until they purchase a top-up credit pack or the next billing period begins. This alert will only evaluate credits at the customer or contract level - seat scoped credits are not included in the calculation. This API call shows how to create a threshold notification when the customer has 10 AI credits remaining using the [/alerts/create](/api-reference/alerts/create-a-threshold-notification) end point. ```json theme={null} { "alert_type": "low_remaining_contract_credit_and_commit_balance_reached", "credit_type_id": "d3cb2827-dcb5-44af-9354-947a7197b9a6", "threshold": 10, "name": "10 AI credits remaining reached", "customer_id": "d8319d6f-8ee0-43a7-b76f-d7587c0a811c" } ``` To set up a threshold notification for seat scoped credits and commits, create a `low_remaining_seat_balance_reached` notification using the [/alerts/create](/api-reference/alerts/create-a-threshold-notification) end point. The `seat_filter` parameter, required on the request body when creating this notification, provides a `seat_group_key` field which is used to scope the notification to seat balances associated with seat-based subscriptions with a specific `seat_group_key` in their `seat_config` configuration. This API call shows how to create a threshold notification when a customer has 15 AI credits remaining for any seat on a subscription with a `seat_group_key` of `seat_id`. ```bash theme={null} curl https://api.metronome.com/v1/alerts/create \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "alert_type": "low_remaining_seat_balance_reached", "threshold": 15, "name": "15 AI credits remaining reached", "credit_type_id": "d3cb2827-dcb5-44af-9354-947a7197b9a6", "customer_id": "d8319d6f-8ee0-43a7-b76f-d7587c0a811c", "seat_filter": { "seat_group_key": "seat_id" } }' ``` To retrieve the alert state for a specific seat, use the [/customer-alerts/get](/api-reference/alerts/get-an-alert) end point. Here's an example of retrieving the alert state for a specific seat: ```bash theme={null} curl https://api.metronome.com/v1/customer-alerts/get \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "5cceec38-51fe-4399-8bed-fcb2a8ad1fb7", "alert_id": "e9c0d89d-040e-4ffc-91f6-001c6954d7a7" "seat_filter": {"seat_group_key": "seat_id", "seat_group_value": "seat123"} }' ``` Optionally, use the `seat_filter.seat_group_value` parameter to scope the notification to a specific seat. Here's an example of creating a threshold notification when a customer has 5 AI credits remaining for a specific seat on a subscription with a `seat_group_key` of `seat_id` and a `seat_group_value` of `seat123`. ```bash theme={null} curl https://api.metronome.com/v1/alerts/create \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "alert_type": "low_remaining_seat_balance_reached", "threshold": 5, "name": "5 AI credits remaining reached", "credit_type_id": "d3cb2827-dcb5-44af-9354-947a7197b9a6", "customer_id": "d8319d6f-8ee0-43a7-b76f-d7587c0a811c", "seat_filter": {"seat_group_key": "seat_id", "seat_group_value": "seat123"} }' ``` ## Visualize seat history As part of your product experience, you may want to present the change in seat quantity over time to provide transparency to your customer: * **Quantity history:** To poll the changes to subscription quantity, use the [/getSubscriptionQuantityHistory](/api-reference/contracts/get-subscription-quantity-history) end point. * **Seat id history:** If managing seats using the `seat_config`, you can poll the history of each `seat_id` using the [/get-subscription-seats-history](/api-reference/contracts/get-subscription-seats-history) end point. ## Visualize seat balance If building a seat-scoped subscription billing model, you likely will want to display the active balance per seat and seat's balance over time. To query this information, use the [/contracts/seatBalances/list](/api-reference/credits-and-commits/list-seat-balances) endpoint: * **Current seat balance:** Passing the `customer_id` and `contract_id` will return the current `balance` for all seats. Passing a `seat_id` to the request body will scope the results to an individual seat. * **Seat ledger history:** To create a view which shows the history of credit grants and associated burn-down, pass `include_ledgers: true` to the request body. Optionally pass in the `starting_at` and `ending_before` dates to filter the response to a specified time period. # Manage subscription lifecycle Source: https://docs.metronome.com/guides/pricing-packaging/subscription/manage-subscription-lifecycle Use the Metronome API to manage your customer's subscription lifecycle including pricing changes, free trials, upgrades, and downgrades. ## Update pricing​ A core benefit of using Metronome subscriptions is centralized management of pricing via the rate card. To change the price of a subscription, change the price of the associated subscription rate on the rate card. All contracts inherit the new pricing and customers are billed at the new rate at the start of the next billing period. **INFO** If you apply an overwrite override to the price of the subscription on the contract, the contract won't inherit changes made on the rate card. It keeps the price assigned on the overwrite. ## Configure a free trial​ Creating a free trial in Metronome follows the general pattern for discounts: apply a rate override on the customer’s contract. If you want to offer a free trial for a subscription you have two options, depending on the desired behavior: * **If the trial period is less than a full billing cycle.** * Create one subscription on the contract that starts on the start date of the contract and ends after the free trial period. Add an override to the subscription rate to change the price to \$0. * Create a second subscription on the contract that starts after the first one ends. * **If the trial period is a full billing cycle.** * Create one subscription on the contract that starts when the contract starts. * Add an override for the trial period to change the rate to \$0 for that period. Once that period ends, the customer is automatically billed at the list rate on the rate card at the start of the next period. **RATE CHANGES** In Metronome, subscriptions can only have one rate per billing period. This enables you to schedule price changes on the rate card without interrupting mid-cycle customers. ## Add a subscription to an existing contract​ Add a new subscription to an existing contract using the `add_subscription` action on the [edit contract end point](/api-reference/contracts/edit-a-contract). Make sure the `entitlement` for the relevant subscription rate is set to `true`. This is most often used to model subscription add-ons. ## Upgrade or downgrade a subscription​ Facilitate a contract transition by using the [create contract endpoint](/api-reference/contracts/edit-a-contract) and specifying the `transition` object `type` to`renewal`. Metronome recommends facilitating upgrade and downgrade motions using contract transitions for a few reasons: * End your first subscription and start the second one with a single API call - automatically handling proration. * Oftentimes different subscription packages might have different rates. Ending one contract and starting a new one provides a clean separation and audit of the original and new rates. * If using credit based subscription models, contract transitions will automatically handle roll-over logic. **DOWNGRADES** Metronome only supports prorating for upgrade motions, such as increasing quantity or adding a new subscription mid-period. For downgrade motions, such as decreasing quantity, the change takes effect at the start of the next billing period. ## Cancel a subscription​ End a subscription in Metronome by either: * Ending the contract by moving the contract end date to the time of cancellation using the [edit contract endpoint](/api-reference/contracts/edit-a-contract). * Ending the subscription on the contract by moving the subscription end date to the time of cancellation using the [edit contract endpoint](/api-reference/contracts/edit-a-contract). If using this method to cancel a hybrid subscription, you must also end the recurring credit separately. For most cancellations, Metronome recommends ending the contract. If the same customer restarts the subscription in the future, create a new contract at that point in time. This enables the Metronome contract to be the source of truth for whether a customer has an active plan for your product. **WARNING** Extending or removing a contract's end date does **not** automatically update the subscription end date if the most recent service period has already been finalized. For in-advance subscriptions, create a new subscription using the [EditContract](/api-reference/contracts/edit-a-contract) endpoint when extending the contract to ensure that the customer will have an active subscription in future service periods. # Provision your customer Source: https://docs.metronome.com/guides/pricing-packaging/subscription/provision-your-customer Once your products and rates are configured, you can provision your customer with a [contract](/api-reference/contracts/create-a-contract). Metronome supports three types of subscription configurations on a contract: * **Standard subscription:** Customers pay a recurring fee each billing period and all usage is either included or paid for separately in-arrears. * **Seat-based credit pool:** Customers pay a recurring fee each billing period and are granted access to a pool of usage credits. Each seat on the subscription draws down from the shared credit pool. Overages are billed at the contract level. * **Individual seat credits:** Customers pay a recurring fee each billing period and are granted access to credits scoped to individual seats. Overages are billed at the contract level. ## Create a standard subscription Subscriptions are configured on the customer's contract. To configure the subscription, you must first ensure the correct subscription rate from the rate card is specified and then complete the subscription configuration ### Pass the subscription config​ For each subscription on a contract, set the `subscriptions` config on the create contract call. Specify: * `subscription_rate`: Similar to overrides, specify which subscription rate on your rate card this config applies to using the `billing_frequency` and `product_id`. * `collection_schedule`: Either `advance` or `arrears`. * `initial_quantity`: The current quantity for the subscription. For seats, this is the initial seat count. For a platform license, this is likely just `1`. * `proration`: Define whether to prorate for mid-period quantity changes and whether mid-period changes should invoice immediately or on the next billing cycle. Optionally include a `rounding` object to round prorated subscription charges for improved invoice presentation. * *Optional fields*: Optionally set the start and end dates of the subscription if different from the contract. Add a name or description for the subscription. These appear on the subscription line item. ### Optionally override the subscription rate Use override functionality to discount the list rate and ensure the rate is `enabled` on the contract. To perform an override on a subscription rate, you must specify both the `billing_frequency` and the `product_id` given that a single `product_id` may map to multiple rates. **WARNING** Metronome will not charge for the subscription on the contract unless there is a subscription config set and the associated rate is `enabled`. ### Customize the billing cycle configuration Customize how subscription billing periods are anchored and where subscription charges appear on invoices using the `billing_cycle_config` object on the subscription. Specify: * `anchor_date`: The date from which Metronome begins generating subscription billing periods. Must be on or before the subscription start date, and is only supported for advance subscriptions. By default, subscriptions anchor to the same date as the contract's usage invoice anchor (typically the 1st of the month). Set a custom `anchor_date` to decouple the subscription billing cycle from the contract — for example, to bill each customer on the anniversary of their subscription start date rather than the first of the month or the contract start date. * `invoice_placement`: Controls where subscription charges appear on invoices. Defaults to `ON_USAGE_INVOICE` so that subscription charges appear on the usage invoice with the matching billing date. Optionally set this field to `ON_SCHEDULED_INVOICE` to place subscription charges on scheduled invoices. If a scheduled invoice with the same billing date already exists, the charge is appended to it; otherwise a new scheduled invoice is created. ### Create the contract See example contract creation below, where a contract is created with a subscription. Note that the subscription is configured to bill for prorated charges immediately, and round the unit price for prorated charges to the nearest dollar (because USD rates are expressed in cents). ```json theme={null} { "customer_id": "4c09936b-455d-4c72-a120-d71b600a7546", "rate_card_id": "740a2ca1-64f6-417d-807a-05f154b3b1fe", "starting_at": "2025-04-23T00:00:00.000Z", "billing_provider_configuration": { "billing_provider_configuration_id": "e045c62b-65e7-4e84-a924-3f06f8b621d0" }, "overrides": [ { "starting_at": "2025-04-01T00:00:00.000Z", "override_specifiers": [ { "billing_frequency": "annual", "product_id": "ed518bcb-acc1-4cd8-85dd-880c2eb38994" } ], "entitled": true } ], "subscriptions": [ { "collection_schedule": "advance", "initial_quantity": 2, "proration": { "invoice_behavior": "bill_immediately", "is_prorated": true, "rounding": { "rounding_method": "HALF_UP", "decimal_places": -2 } }, "subscription_rate": { "billing_frequency": "annual", "product_id": "ed518bcb-acc1-4cd8-85dd-880c2eb38994" }, "description": "pro plan no additions", "name": "Pro Plan", "custom_fields": { "plan_tier": "pro" } } ] } ``` **INVOICING** You must specify a `billing_provider_configuration` on the contract for Metronome to successfully route invoices and collect payment on your behalf. See this guide for more information on [billing configurations](/guides/get-started/core-concepts/provision-customer#add-a-billing-configuration-to-a-customer). **DIMENSIONAL PRICING** If you're using a seat-based credit pool or individual seat-based credits, we do not recommend using dimensional pricing. Contact us via the [Metronome support portal](https://support.metronome.com/) to help determine the best integration pattern. ## Seat-based credit pool Commonly, Metronome clients offer some amount of usage credits as part of their subscription offering. One way to model this is to provide a shared pool of credits that all seats on the subscription can consume. In order to model this in Metronome, you would follow the same instructions above for creating the subscription but additionally link the subscription to a [recurring credit](/guides/pricing-packaging/apply-credits-and-commits/create-a-pre-paid-commit#provision-recurring-usage-credits%E2%80%8B). To link a subscription to a recurring credit on contract creation, add a `temporary_id` to your subscription config. Then, on the recurring credit config, reference the `temporary_id`. Each billing period, a credit balance equal to `access_amount` will be provided on the contract per seat. When new seats are added to the contract, new balance will be made available in the shared pool based upon the defined proration settings. ```json theme={null} { "customer_id": "4c09936b-455d-4c72-a120-d71b600a7546", "rate_card_id": "740a2ca1-64f6-417d-807a-05f154b3b1fe", "starting_at": "2025-04-23T00:00:00.000Z", "billing_provider_configuration": { "billing_provider_configuration_id": "e045c62b-65e7-4e84-a924-3f06f8b621d0" }, "overrides": [ { "starting_at": "2025-04-01T00:00:00.000Z", "override_specifiers": [ { "billing_frequency": "annual", "product_id": "ed518bcb-acc1-4cd8-85dd-880c2eb38994" } ], "entitled": true } ], "subscriptions": [ { "collection_schedule": "advance", "initial_quantity": 2, "proration": { "invoice_behavior": "bill_on_next_collection_date", "is_prorated": true }, "subscription_rate": { "billing_frequency": "annual", "product_id": "ed518bcb-acc1-4cd8-85dd-880c2eb38994" }, "description": "pro plan no additions", "name": "Pro Plan", "custom_fields": { "plan_tier": "pro" }, "temporary_id": "pro_plan_annual" } ], "recurring_credits": [ { "access_amount": { "credit_type_id": "d3cb2827-dcb5-44af-9354-947a7197b9a6", "unit_price": 100 }, "commit_duration": { "value": 1, "unit": "periods" }, "priority": 1, "product_id": "652e1298-7638-45a8-b691-cdf47e46cbc8", "starting_at": "2025-06-01T00:00:00Z", "subscription_config": { "subscription_id": "pro_plan_annual", "apply_seat_increase_config": { "is_prorated": true } } } ] } ``` **TIP** If you have an existing contract with a standard subscription, you can link it to a recurring credit using the `add_recurring_credits` object on the `/contracts/edit` end point. ## Individual seat credit Alternatively, some organizations may wish to issue seat-scoped credits as part of their subscription package. In this model, each seat is entitled to a certain balance each period and only they can consume that balance. To configure seat-scoped credits, you need to specify a user ID for each seat. Metronome uses this ID to map usage to an individual seat. **TIP** By default, Metronome supports up to 1000 seats with individual seat credits. Contact us via the [Metronome support portal](https://support.metronome.com/) if your use case requires more than 1000 seats. ### Prerequisites Before configuring individual seat credits on a contract, you must set up seat-based pricing on your usage products. This involves three steps: Add a [group key](/guides/get-started/core-concepts/create-billable-metrics#3-define-group-keys) on the billable metric that underlies your usage product e.g. `seat_id`. Group keys must be defined at the metric level before they can be used on products. Group keys cannot be edited after a streaming billable metric is created. If your existing metric doesn't include `seat_id` as a group key, you need to create a new metric with it defined. Set `seat_id` as a [presentation group key](/guides/get-started/core-concepts/create-products-contracts#presentation-group-keys) on each usage product that should track per-seat consumption. The product's group keys must reference group keys already defined on the underlying billable metric. Every usage event you send to Metronome must include a `seat_id` property so usage is correctly attributed to the right seat. Here's an example: ```json theme={null} { "event_type": "video_generation", "properties": { "model_name": "claude-3-opus", "resolution": "1080p", "environment": "production", "video_duration_seconds": 20, "seat_id": "example@metronome.com" }, "transaction_id": "21f00039-0572-4f63-bf0f-b19faa3d10f8", "customer_id": "94fbf9f3-2826-4503-8446-013c68817744", "timestamp": "2025-10-15T15:23:48.751Z" } ``` The `seat_id` value should be a stable, unique identifier for each seat—such as an email address or user ID. ### Configure the contract Specify [`quantity_management_mode`](/api-reference/contracts/create-a-contract#body-subscriptions-items-quantity_management_mode) as `SEAT_BASED`. Then, instead of using the `quantity` field to pass the number of seats, populate the `seat_config`. This object is composed of three fields: * `initial_seat_ids`: An array representing the unique identifier for each seat. * `initial_unassigned_seats_quantity`: The number of seats that do not yet have a user associated to it. This will add to the total seat count for the subscription, but will not generate credits until a `seat_id` is specified. * `seat_group_key`: The presentation group key provided on the usage products. Metronome uses this key to map the `seat_id` to the correct usage and products. An example contract call is shown below: ```json theme={null} { "customer_id": "1f79c5c6-400a-4be4-9573-30c667454e4c", "rate_card_id": "79b2716d-530c-4ff9-86f8-3ee91f442b1b", "starting_at": "2025-09-01T00:00:00Z", "name": "Extend RC 2", "billing_provider_configuration": { "billing_provider_configuration_id": "e045c62b-65e7-4e84-a924-3f06f8b621d0" }, "subscriptions": [ { "collection_schedule": "advance", "proration": { "invoice_behavior": "bill_on_next_collection_date", "is_prorated": true }, "subscription_rate": { "billing_frequency": "annual", "product_id": "ed518bcb-acc1-4cd8-85dd-880c2eb38994" }, "description": "pro plan no additions", "name": "Pro Plan", "custom_fields": { "plan_tier": "pro" }, "quantity_management_mode": "SEAT_BASED", "seat_config": { "initial_seat_ids": ["seat1@metronome.com", "seat2@metronome.com", "seat3@metronome.com"], "seat_group_key": "seat_id" }, "temporary_id": "pro_plan_annual" } ], "recurring_commits": [ { "product_id": "35a467c7-fc24-46c2-884b-66af8d349674", "access_amount": { "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "unit_price": 1000 }, "invoice_amount": { "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "unit_price": 1000, "quantity": 1 }, "priority": 100, "starting_at": "2025-09-01T00:00:00Z", "ending_before": "2025-11-16T00:00:00Z", "commit_duration": { "value": 1 }, "rollover_fraction": 0.5, "subscription_config": { "apply_seat_increase_config": { "is_prorated": true }, "subscription_id": "pro_plan_annual", "allocation": "INDIVIDUAL" } } ] } ``` # Overview Source: https://docs.metronome.com/guides/pricing-packaging/subscription/subscription-overview Metronome's billing platform supports subscriptions as a product type. Subscriptions are recurring fees billed on a schedule. Use subscription fees for seat based billing models, platform fees, or other recurring charges. ## How subscriptions work​ Learn how to work with the subscription data model to support your use cases. Subscription data model ### Products​ The product is what ultimately drives the line item on the customer's invoice. Create a subscription product for each type of subscription you offer. For example, if you offer a Good, Better, and Best plan, create a product for each. Think of products as similar to SKUs. ### Rates​ Add a rate to the rate card for each standard price you offer. The price set on the rate card is the *price for a quantity of 1.* A product can map to multiple rates. For example, consider a scenario where you sell your Good, Better, and Best subscriptions at different rates depending on whether your customer pays for it monthly, quarterly, or annually. To model this in Metronome, create 9 rates, with 3 rates per product, to represent the distinct prices for each billing frequency. ### Contracts​ With contracts, you can encode different types of billing models in Metronome. When a customer purchases a subscription plan, create a contract for the customer and set `entitlement`to `true` for the corresponding subscription rate (for example, Good - Monthly). Use the contract to set quantity, proration behavior, and collection behavior: in-advance or in-arrears.Metronome doesn't distinguish between types of subscription, such as a recurring platform fee or a seat-based subscription. `quantity` defines how many subscriptions a customer has. Most commonly, this models how many seats a customer is entitled to. Optionally define whether credit balance should provisioned as part of the subscription. Credits can be pooled at the subscription level or scoped per seat. ### Learn how to manage subscriptions within Metronome Create subscription products and add them to your rate card to define standard list prices. Create contracts for your customers based on the subscription plan they choose. Supports standard subscription recurring fees and hybrid credit models. Change the count of seats per subscription and optionally associate a seat to user id. View changes over time and manage seat balance for hybrid models. Moodel subscription transitions within Metronome. # SQL cookbook Source: https://docs.metronome.com/guides/reporting-insights/data-export/cookbook Common SQL queries and examples for analyzing your Metronome data warehouse exports This page provides practical SQL query examples for working with your Metronome data exports. Use these queries as starting points for your own analysis and reporting. All examples use standard SQL syntax. Adjust date functions and syntax as needed for your specific data warehouse (Snowflake, BigQuery, Redshift, etc.). ## Core Entities ### Customers Count all non-archived customers. ```sql theme={null} SELECT COUNT(0) FROM customer WHERE archived_at IS NULL; ``` **Tables:** [`customer`](/guides/reporting-insights/data-export/database-reference#customer) ### Events Track event ingestion volume over time. ```sql theme={null} SELECT DATE_TRUNC('MONTH', timestamp) AS month, COUNT(0) AS event_count FROM events GROUP BY 1 ORDER BY 1; ``` **Tables:** [`events`](/guides/reporting-insights/data-export/database-reference#events) ## Invoicing ### Finalized Invoices Calculate total invoice counts and amounts by month. ```sql theme={null} SELECT DATE_TRUNC("MONTH", end_timestamp) AS month, COUNT(0) AS invoice_count, SUM(total) AS invoice_total FROM invoice GROUP BY 1 ORDER BY 1; ``` **Tables:** [`invoice`](/guides/reporting-insights/data-export/database-reference#invoice) Break down monthly revenue by line item type. ```sql theme={null} SELECT DATE_TRUNC("MONTH", i.end_timestamp) AS month, li.line_item_type, SUM(li.total) AS total FROM invoice i JOIN line_item li ON i.id = li.invoice_id GROUP BY 1, 2 ORDER BY 2, 1; ``` **Tables:** [`invoice`](/guides/reporting-insights/data-export/database-reference#invoice), [`line_item`](/guides/reporting-insights/data-export/database-reference#line-item) ### Draft Invoices Track draft invoice progression over time. ```sql theme={null} SELECT snapshot_time, COUNT(0) AS invoice_count, SUM(total) AS invoice_total FROM draft_invoice GROUP BY 1 ORDER BY 1; ``` **Tables:** [`draft_invoice`](/guides/reporting-insights/data-export/database-reference#draft-invoice) Get the latest draft invoice totals grouped by contract. ```sql theme={null} SELECT contract_id, COUNT(0) AS invoice_count, SUM(total) AS invoice_total FROM draft_invoice WHERE snapshot_time = (SELECT MAX(snapshot_time) FROM draft_invoice) GROUP BY 1 ORDER BY 1; ``` **Tables:** [`draft_invoice`](/guides/reporting-insights/data-export/database-reference#draft-invoice) ### Invoice Breakdowns Analyze line item metrics from the most recent draft breakdowns snapshot. ```sql theme={null} WITH max_draft_breakdown_snapshot AS ( SELECT max(snapshot_timestamp) AS max_snapshot_ts FROM breakdowns_draft_invoices ) SELECT i.breakdown_start_timestamp, li.name, SUM(li.quantity) AS quantity, SUM(li.total/100) AS total_dollars FROM breakdowns_draft_invoices i JOIN breakdowns_draft_line_items li ON i.id = li.invoice_breakdown_id AND i.snapshot_timestamp = li.snapshot_timestamp WHERE i.environment_type = 'PRODUCTION' AND i.snapshot_timestamp = (SELECT max_snapshot_ts FROM max_draft_breakdown_snapshot) AND li.total >= 0 GROUP BY 1, 2 ORDER BY 1 DESC; ``` **Tables:** [`breakdowns_draft_invoices`](/guides/reporting-insights/data-export/database-reference#breakdowns-draft-invoices), [`breakdowns_draft_line_items`](/guides/reporting-insights/data-export/database-reference#breakdowns-draft-line-items) Get detailed draft line item breakdowns per customer and invoice. ```sql theme={null} WITH max_draft_breakdown_snapshot AS ( SELECT max(snapshot_timestamp) AS max_snapshot_ts FROM breakdowns_draft_invoices ) SELECT i.customer_id, i.breakdown_start_timestamp, i.invoice_id, li.name, li.quantity, li.total/100 AS total_dollars FROM breakdowns_draft_invoices i JOIN breakdowns_draft_line_items li ON i.id = li.invoice_breakdown_id AND i.snapshot_timestamp = li.snapshot_timestamp WHERE i.environment_type = 'PRODUCTION' AND i.snapshot_timestamp = (SELECT max_snapshot_ts FROM max_draft_breakdown_snapshot) GROUP BY 1, 2 ORDER BY 1 DESC; ``` **Tables:** [`breakdowns_draft_invoices`](/guides/reporting-insights/data-export/database-reference#breakdowns-draft-invoices), [`breakdowns_draft_line_items`](/guides/reporting-insights/data-export/database-reference#breakdowns-draft-line-items) ## Contracts List all archived contracts. ```sql theme={null} SELECT * FROM contracts_contracts WHERE archived_at IS NOT NULL; ``` **Tables:** [`contracts_contracts`](/guides/reporting-insights/data-export/database-reference#contracts-contracts) Get the latest pricing overrides for a specific contract. ```sql theme={null} SELECT * FROM contracts_overrides WHERE contract_id = '' ORDER BY updated_at DESC; ``` **Tables:** [`contracts_overrides`](/guides/reporting-insights/data-export/database-reference#contracts-overrides) Replace `` with your actual contract ID. Analyze rate card coverage by counting active entries. ```sql theme={null} SELECT crc.id AS rate_card_id, COUNT(*) FROM contracts_rate_cards crc JOIN contracts_rate_card_entries crce ON crc.id = crce.rate_card_id WHERE crce.ending_before > NOW() GROUP BY 1 ORDER BY 1; ``` **Tables:** [`contracts_rate_cards`](/guides/reporting-insights/data-export/database-reference#contracts-rate-cards), [`contracts_rate_card_entries`](/guides/reporting-insights/data-export/database-reference#contracts-rate-card-entries) ## Alerts Get all active alerts configured to send webhooks. ```sql theme={null} SELECT id, name, alert_type, threshold FROM alert WHERE webhooks_enabled = TRUE AND disabled_at IS NULL; ``` **Tables:** [`alert`](/guides/reporting-insights/data-export/database-reference#alert) Analyze alert trigger frequency by day. ```sql theme={null} SELECT DATE_TRUNC("DAY", ah.created_at) AS alert_date, alert.name, COUNT(alert.id) AS triggered_count FROM customer_alert_history ah JOIN alert ON ah.alert_id = alert.id GROUP BY 1, 2 ORDER BY 1; ``` **Tables:** [`customer_alert_history`](/guides/reporting-insights/data-export/database-reference#customer-alert-history), [`alert`](/guides/reporting-insights/data-export/database-reference#alert) # Database reference Source: https://docs.metronome.com/guides/reporting-insights/data-export/database-reference This page provides a comprehensive schema reference for all data exported from Metronome to your data warehouse. Use this reference to understand the structure and contents of each table available in your exports. For SQL query examples, see the [SQL cookbook](/guides/reporting-insights/data-export/cookbook). **NULLABLE COLUMNS** Due to our export methodology, all columns may appear as nullable in your destination schema. ## Core entities Foundational data types and entities used throughout Metronome. ### `billable_metric` | Column | Type | Description | | ------------------ | ----------- | ----------------------------------------------------------------- | | `id` | `string` | ID of the billable metric | | `environment_type` | `string` | The Metronome environment, `SANDBOX` or `PRODUCTION` | | `aggregate` | `string` | The aggregation type | | `aggregate_keys` | `json` | The keys used for aggregation | | `group_keys` | `json` | The group by keys associated with this billable metric | | `name` | `string` | Name of the billable metric | | `created_at` | `timestamp` | The timestamp (UTC) of when the billable\_metric was created | | `archived_at` | `timestamp` | The timestamp (UTC) of when the billable\_metric was archived | | `updated_at` | `timestamp` | The timestamp (UTC) of when the billable\_metric was last updated | ### `credit_type` | Column | Type | Description | | ------------------------ | ----------- | ----------------------------------------------------------- | | `_metronome_metadata_id` | `string` | Metronome metadata ID | | `id` | `string` | The credit type ID | | `environment_type` | `string` | The Metronome environment, `SANDBOX` or `PRODUCTION` | | `name` | `string` | The name of the credit type | | `is_currency` | `boolean` | Whether or not the credit type is a currency, TRUE or FALSE | | `updated_at` | `timestamp` | The timestamp (UTC) this row was last updated | ### Events The full set of deduplicated raw events received by Metronome, regardless of whether or not they matched a billable metric. ### `events` | Column | Type | Description | | ------------------------ | ----------- | ---------------------------------------------------- | | `transaction_id` | `string` | The unique ID of the event | | `environment_type` | `string` | The Metronome environment, `SANDBOX` or `PRODUCTION` | | `customer_id` | `string` | The ID of the customer the event applies to | | `timestamp` | `timestamp` | The timestamp (UTC) of the event | | `event_type` | `string` | The event type | | `properties` | `json` | The properties of the event | | `_metronome_metadata_id` | `string` | Metronome metadata ID | | `updated_at` | `timestamp` | The timestamp (UTC) this row was last updated | ### Customers Includes customer metadata stored in Metronome including their ingest aliases, which can be joined with the `events` table. The `archived_at` column is used to determine if the customer is active. ### `customer` | Column | Type | Description | | ------------------------------ | ----------- | -------------------------------------------------------------------- | | `id` | `string` | The Metronome ID of the customer | | `environment_type` | `string` | The Metronome environment, `SANDBOX` or `PRODUCTION` | | `name` | `string` | The name of the customer | | `ingest_aliases` | `json` | The ingest aliases of the customer | | `salesforce_account_id` | `string` | The Salesforce account ID for the customer | | `billing_provider_type` | `string` | The billing provider connected to the customer | | `billing_provider_customer_id` | `string` | The billing provider ID of the customer | | `custom_fields` | `json` | Custom fields attached to the customer | | `created_at` | `timestamp` | The timestamp (UTC) of when the customer was created | | `updated_at` | `timestamp` | The timestamp (UTC) of when the customer was last updated | | `archived_at` | `timestamp` | The timestamp (UTC) of when the customer was archived, if applicable | ## Invoicing All invoice-related data including finalized invoices, drafts, and detailed breakdowns. ### Finalized invoices Includes all invoices to customers that have been finalized or voided. No further changes can be made to these invoices or their corresponding line items. ### `invoice` | Column | Type | Description | | ------------------------------------------ | ----------- | --------------------------------------------------------------------------------- | | `id` | `string` | The Metronome invoice ID | | `environment_type` | `string` | The Metronome environment, `SANDBOX` or `PRODUCTION` | | `status` | `string` | The Metronome invoice status: `FINALIZED` or `VOID` | | `total` | `decimal` | The invoice total | | `credit_type_id` | `string` | The credit type ID for the invoice | | `credit_type_name` | `string` | The name of the credit type associated with the invoice | | `customer_id` | `string` | The Metronome ID of the customer | | `plan_id` | `string` | Deprecated field - expect to be `NULL` | | `plan_name` | `string` | Deprecated field - expect to be `NULL` | | `contract_id` | `string` | The contract ID associated with the invoice | | `billing_provider_invoice_id` | `string` | The external invoice ID from the billing provider (e.g., Stripe) | | `billing_provider_type` | `string` | The type of external system billing provider (e.g. Stripe) | | `billing_provider_invoice_created_at` | `timestamp` | The timestamp (UTC) the external invoice was created by Metronome | | `billing_provider_invoice_external_status` | `string` | The status of the invoice in the external system (e.g. Stripe) | | `invoice_label` | `string` | The categorical label of the invoice | | `metadata` | `json` | [`Metadata`](/guides/reporting-insights/data-export/database-reference/#metadata) | | `start_timestamp` | `timestamp` | Beginning of the usage period that this invoice covers (UTC) | | `end_timestamp` | `timestamp` | End of the usage period that this invoice covers (UTC) | | `issued_at` | `timestamp` | The timestamp (UTC) of when the invoice was issued | | `updated_at` | `timestamp` | The timestamp (UTC) of when this row was last updated | ### `line_item` | Column | Type | Description | | ---------------------- | ----------- | ------------------------------------------------------------------------------------------------ | | `id` | `string` | The line item ID | | `environment_type` | `string` | The Metronome environment, `SANDBOX` or `PRODUCTION` | | `invoice_id` | `string` | The Metronome invoice ID associated with the line item | | `credit_grant_id` | `string` | Deprecated field - expect to be `NULL` | | `credit_type_id` | `string` | The credit type ID associated with the line item | | `credit_type_name` | `string` | The name of the credit type associated with the line item | | `name` | `string` | The line item description | | `quantity` | `decimal` | The quantity associated with the line item; this will always be `1` for invoice adjustments | | `total` | `decimal` | The line item total | | `commit_id` | `string` | The commit ID associated with the line item. Only present for Contract Invoices | | `product_id` | `string` | The product ID associated with the line item; this will always be `NULL` for invoice adjustments | | `group_key` | `string` | The group key associated with the line item | | `group_value` | `string` | The group value associated with the line item | | `unit_price` | `decimal` | The price associated with the line item | | `pricing_group_values` | `json` | Optional pricing group values array | | `metadata` | `json` | [`Metadata`](/guides/reporting-insights/data-export/database-reference/#metadata) | | `subscription_id` | `string` | The subscription ID associated with the line item. Only present for subscription charges. | | `is_prorated` | `boolean` | Indicates if the value is prorated over the period. For subscription charges only. | | `starting_at` | `timestamp` | The timestamp (UTC) of when the line item is effective from (inclusive) | | `ending_before` | `timestamp` | The timestamp (UTC) of when the line item is effective to (exclusive) | | `updated_at` | `timestamp` | The timestamp (UTC) of when the line item was last updated | ### Draft invoices Includes all invoices to customers that are in a draft state. These tables are daily snapshots of invoices based on each customer's configuration and usage at a point-in-time during the day. The `updated_at` column is the time that the invoice row was calculated while the `snapshot_time` corresponds to the start of day (UTC). An invoice row will be populated once per day throughout a billing period until it is finalized or voided. If an invoice is in a `DRAFT_INCOMPLETE` state, it means that Metronome hasn't fully computed the invoice. There will be no line items or total on the invoice. Exporting these invoices lets you know that the invoice exists, but Metronome has failed to compute it for some reason. Exporting incomplete invoices enables Metronome to send data to the specified destination as soon as possible. We expect these incomplete invoices to be hydrated in future snapshots. ### `draft_invoice` | Column | Type | Description | | ------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------- | | `_metronome_metadata_id` | `string` | Unique identifier for each draft invoice ID + snapshot\_time pair | | `id` | `string` | The Metronome invoice ID | | `environment_type` | `string` | The Metronome environment, `SANDBOX` or `PRODUCTION` | | `snapshot_time` | `timestamp` | The timestamp (UTC) aligning with the start of the snapshot | | `status` | `string` | The Metronome invoice status: `DRAFT` or `DRAFT_INCOMPLETE` (see the `invoice` table for `FINALIZED` and `VOID` invoices) | | `total` | `decimal` | The invoice total | | `credit_type_id` | `string` | The credit type ID for the invoice | | `credit_type_name` | `string` | The name of the credit type associated with the invoice | | `customer_id` | `string` | The Metronome ID of the customer | | `plan_id` | `string` | Deprecated field - expect to be `NULL` | | `plan_name` | `string` | Deprecated field - expect to be `NULL` | | `contract_id` | `string` | The contract ID associated with the invoice | | `billable_status` | `string` | Billable status of the invoice, `BILLABLE` or `UNBILLABLE` | | `billing_provider_invoice_id` | `string` | The external invoice ID from the billing provider (e.g., Stripe) | | `billing_provider_invoice_created_at` | `timestamp` | The timestamp (UTC) of when the external invoice was created by Metronome | | `label` | `string` | The categorical label of the invoice | | `start_timestamp` | `timestamp` | Beginning of the usage period that this invoice covers (UTC) | | `end_timestamp` | `timestamp` | End of the usage period that this invoice covers (UTC) | | `updated_at` | `timestamp` | The timestamp (UTC) this row was last updated | ### `draft_line_item` | Column | Type | Description | | ------------------------ | ----------- | ------------------------------------------------------------------------------------------------ | | `_metronome_metadata_id` | `string` | Opaque unique identifier for each row | | `id` | `string` | The line item ID | | `environment_type` | `string` | The Metronome environment, `SANDBOX` or `PRODUCTION` | | `snapshot_time` | `timestamp` | The timestamp (UTC) aligning with the start of the snapshot | | `invoice_id` | `string` | The Metronome invoice ID associated with the line item | | `credit_grant_id` | `string` | Deprecated field - expect to be `NULL` | | `credit_type_id` | `string` | The credit type ID associated with the line item | | `credit_type_name` | `string` | The name of the credit type associated with the line item | | `name` | `string` | The line item description | | `quantity` | `decimal` | The quantity associated with the line item; this will always be `1` for invoice adjustments | | `total` | `decimal` | The line item total | | `commit_id` | `string` | The commit ID associated with the line item. Only present for Contract Invoices | | `product_id` | `string` | The product ID associated with the line item; this will always be `NULL` for invoice adjustments | | `group_key` | `string` | The group key associated with the line item | | `group_value` | `string` | The group value associated with the line item | | `unit_price` | `decimal` | The price associated with the line item | | `pricing_group_values` | `json` | Optional pricing group values array | | `subscription_id` | `string` | The subscription ID associated with the line item. Only present for subscription charges. | | `is_prorated` | `boolean` | Indicates if the value is prorated over the period. For subscription charges only. | | `metadata` | `json` | [`Metadata`](/guides/reporting-insights/data-export/database-reference/#metadata) | | `starting_at` | `timestamp` | The timestamp (UTC) of when the line item is effective from (inclusive) | | `ending_before` | `timestamp` | The timestamp (UTC) of when the line item is effective to (exclusive) | | `updated_at` | `timestamp` | The timestamp (UTC) of when the line item was last updated | ### Invoice breakdowns Invoice breakdowns are stored in four separate tables that are exported to your warehouse destination daily. The draft invoice data exports in snapshots that contains all month-to-date breakdown periods up to the snapshot timestamp. This ensures that any mid-billing period pricing and packaging changes, as well as backdated usage data, correctly reflect in the most recent draft invoice breakdown snapshot. Finalized invoice breakdowns export incrementally as invoices finalize. **INVOICE BREAKDOWN FILTERS** To reduce the volume of data exported to your data warehouse destination, you can filter invoice breakdown exports to ignore: * All \$0 total and >0 quantity invoices and line items * All \$0 and 0 quantity invoices and line items To enable filters, contact us via the [Metronome support portal](https://support.metronome.com/). ### `breakdowns_invoices` | Column | Type | Description | | --------------------------- | ----------- | --------------------------------------------------------------------------------- | | `id` | `string` | The Metronome invoice breakdown ID | | `environment_type` | `string` | The Metronome environment, `SANDBOX` or `PRODUCTION` | | `snapshot_timestamp` | `timestamp` | The timestamp (UTC) aligning with the start of the snapshot | | `invoice_id` | `string` | The Metronome invoice ID associated with the breakdown | | `customer_id` | `string` | The Metronome customer ID associated with the breakdown | | `transfer_id` | `string` | The Metronome transfer ID for this invoice breakdown | | `credit_type_id` | `string` | The ID of the credit type associated with the invoice | | `net_payment_term_days` | `integer` | The net payment term in days associated with the invoice | | `credit_type_name` | `string` | The name of the credit type associated with the invoice | | `subtotal` | `decimal` | Deprecated field—expect to be `NULL` unless using Plans data model | | `total` | `decimal` | The total for the invoice | | `type` | `string` | The invoice type | | `external_invoice` | `json` | The external invoice data | | `plan_id` | `string` | Deprecated field—expect to be `NULL` unless using Plans data model | | `contract_id` | `string` | The contract ID associated with the invoice | | `amendment_id` | `string` | The amendment ID associated with the invoice | | `custom_fields` | `json` | Custom fields that apply to the invoice | | `billable_status` | `string` | The invoice's billable status | | `window_size` | `string` | The size of the breakdown window—typically `DAILY` | | `metadata` | `json` | [`Metadata`](/guides/reporting-insights/data-export/database-reference/#metadata) | | `issued_at` | `timestamp` | The timestamp (UTC) when this invoice was issued | | `invoice_start_timestamp` | `timestamp` | Beginning of the usage period that this invoice covers (UTC) (inclusive) | | `invoice_end_timestamp` | `timestamp` | End of the usage period that this invoice covers (UTC) (exclusive) | | `breakdown_start_timestamp` | `timestamp` | The timestamp corresponding with the start of the breakdown window (inclusive) | | `breakdown_end_timestamp` | `timestamp` | The timestamp corresponding with the end of the breakdown window (exclusive) | | `updated_at` | `timestamp` | The timestamp (UTC) when this row last updated | ### `breakdowns_line_items` | Column | Type | Description | | --------------------------- | ----------- | -------------------------------------------------------------------------------------------------------------------------- | | `id` | `string` | The Metronome line item breakdown ID | | `environment_type` | `string` | The Metronome environment, `SANDBOX` or `PRODUCTION` | | `snapshot_timestamp` | `timestamp` | The timestamp (UTC) aligning with the start of the snapshot | | `watermark_timestamp` | `timestamp` | The timestamp indicating the latest modification to this row | | `invoice_breakdown_id` | `string` | The Metronome invoice breakdown ID associated with the line item | | `name` | `string` | The name of the line item associated with the breakdown | | `transfer_id` | `string` | The Metronome transfer ID for this line item breakdown | | `group_key` | `string` | The group key associated with the line item | | `group_value` | `string` | The group value associated with the line item | | `quantity` | `decimal` | The quantity of this line item breakdown row—always 1 for invoice adjustments | | `total` | `decimal` | The total for the line item breakdown | | `unit_price` | `decimal` | The unit price for the line item | | `product_id` | `string` | The ID of the product for the line item—always NULL for invoice adjustments | | `product_type` | `string` | The type of product for the line item breakdown | | `credit_type_id` | `string` | The credit type ID associated with the line item | | `credit_type_name` | `string` | The name of the credit type associated with the line item | | `commit_id` | `string` | The commit ID associated with the line item breakdown | | `commit_segment_id` | `string` | The commit segment ID associated with the line item breakdown | | `commit_type` | `string` | The commit type associated with the line item breakdown | | `subscription_id` | `string` | The subscription ID associated with the line item breakdown—only present for subscription charges. | | `is_prorated` | `boolean` | Indicates if the value is prorated over the period. For subscription charges only. | | `line_item_id` | `string` | The unique line item id that can be used to join with records in the line\_item table | | `line_item_type` | `string` | The unique line item type that defines the type of revenue represented in the line item | | `custom_fields` | `json` | Custom fields that apply to the breakdown | | `pricing_group_values` | `json` | The pricing group values associated with the line item breakdown | | `presentation_group_values` | `json` | The presentation group values associated with the line item breakdown | | `billable_metric_id` | `string` | The billable metric ID that applies to the line item breakdown | | `metadata` | `json` | Additional metadata in JSON format (see [`Metadata`](/guides/reporting-insights/data-export/database-reference/#metadata)) | | `breakdown_start_timestamp` | `timestamp` | The timestamp corresponding with the start of the breakdown window (inclusive) | | `breakdown_end_timestamp` | `timestamp` | The timestamp corresponding with the end of the breakdown window (exclusive) | | `updated_at` | `timestamp` | The timestamp (UTC) when this row last updated | ### `breakdowns_draft_invoices` | Column | Type | Description | | --------------------------- | ----------- | ------------------------------------------------------------------------------ | | `id` | `string` | The Metronome invoice breakdown ID | | `environment_type` | `string` | The Metronome environment, `SANDBOX` or `PRODUCTION` | | `snapshot_timestamp` | `timestamp` | The timestamp (UTC) aligning with the start of the snapshot | | `invoice_id` | `string` | The Metronome invoice ID associated with the breakdown | | `customer_id` | `string` | The Metronome customer ID associated with the breakdown | | `transfer_id` | `string` | The Metronome transfer ID for this invoice breakdown | | `credit_type_id` | `string` | The ID of the credit type associated with the invoice | | `net_payment_term_days` | `integer` | The net payment term in days associated with the invoice | | `credit_type_name` | `string` | The name of the credit type associated with the invoice | | `subtotal` | `decimal` | Deprecated field—expect to be `NULL` unless using Plans data model | | `total` | `decimal` | The total for the invoice | | `type` | `string` | The invoice type | | `external_invoice` | `json` | The external invoice data | | `plan_id` | `string` | Deprecated field—expect to be `NULL` unless using Plans data model | | `contract_id` | `string` | The contract ID associated with the invoice | | `amendment_id` | `string` | The amendment ID associated with the invoice | | `custom_fields` | `json` | Custom fields that apply to the invoice | | `billable_status` | `string` | The invoice's billable status | | `window_size` | `string` | The size of the breakdown window—typically `DAILY` | | `metadata` | `json` | Additional metadata in JSON format | | `issued_at` | `timestamp` | The timestamp (UTC) when this invoice was issued | | `invoice_start_timestamp` | `timestamp` | Beginning of the usage period that this invoice covers (UTC) (inclusive) | | `invoice_end_timestamp` | `timestamp` | End of the usage period that this invoice covers (UTC) (exclusive) | | `breakdown_start_timestamp` | `timestamp` | The timestamp corresponding with the start of the breakdown window (inclusive) | | `breakdown_end_timestamp` | `timestamp` | The timestamp corresponding with the end of the breakdown window (exclusive) | | `updated_at` | `timestamp` | The timestamp (UTC) when this row last updated | ### `breakdowns_draft_line_items` | Column | Type | Description | | --------------------------- | ----------- | -------------------------------------------------------------------------------------------------------------------------- | | `id` | `string` | The Metronome line item breakdown ID | | `environment_type` | `string` | The Metronome environment, `SANDBOX` or `PRODUCTION` | | `snapshot_timestamp` | `timestamp` | The timestamp (UTC) aligning with the start of the snapshot | | `watermark_timestamp` | `timestamp` | The timestamp indicating the latest modification to this row | | `invoice_breakdown_id` | `string` | The Metronome invoice breakdown ID associated with the line item | | `name` | `string` | The name of the line item associated with the breakdown | | `transfer_id` | `string` | The Metronome transfer ID for this line item breakdown | | `group_key` | `string` | The group key associated with the line item | | `group_value` | `string` | The group value associated with the line item | | `quantity` | `decimal` | The quantity of this line item breakdown row; always 1 for invoice adjustments | | `total` | `decimal` | The total for the line item breakdown | | `unit_price` | `decimal` | The unit price for the line item | | `product_id` | `string` | The ID of the product for the line item; always NULL for invoice adjustments | | `product_type` | `string` | The type of product for the line item breakdown | | `credit_type_id` | `string` | The credit type ID associated with the line item | | `credit_type_name` | `string` | The name of the credit type associated with the line item | | `commit_id` | `string` | The commit ID associated with the line item breakdown | | `commit_segment_id` | `string` | The commit segment ID associated with the line item breakdown | | `commit_type` | `string` | The commit type associated with the line item breakdown | | `subscription_id` | `string` | The subscription ID associated with the line item breakdown; only present for subscription charges. | | `is_prorated` | `boolean` | Indicates if the value is prorated over the period. For subscription charges only. | | `line_item_id` | `string` | The unique line item id that can be used to join with records in the line\_item table | | `line_item_type` | `string` | The unique line item type that defines the type of revenue represented in the line item | | `custom_fields` | `json` | Custom fields that apply to the breakdown | | `pricing_group_values` | `json` | The pricing group values associated with the line item breakdown | | `presentation_group_values` | `json` | The presentation group values associated with the line item breakdown | | `billable_metric_id` | `string` | The billable metric ID that applies to the line item breakdown | | `metadata` | `json` | Additional metadata in JSON format (see [`Metadata`](/guides/reporting-insights/data-export/database-reference/#metadata)) | | `breakdown_start_timestamp` | `timestamp` | The timestamp corresponding with the start of the breakdown window (inclusive) | | `breakdown_end_timestamp` | `timestamp` | The timestamp corresponding with the end of the breakdown window (exclusive) | | `updated_at` | `timestamp` | The timestamp (UTC) when this row last updated | ## Contracts Includes contract information. The `archived_at` column defines whether the contract has been archived or not. ### `contracts_contracts` | Column | Type | Description | | ------------------------------------- | --------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `id` | `string` | ID of the contract | | `environment_type` | `string` | The Metronome environment, `SANDBOX` or `PRODUCTION` | | `snapshot_id` | `string` | The snapshot ID for the contract row | | `name` | `string` | Name of the contract | | `customer_id` | `string` | The customer ID of the contract | | `package_id` | `string` | The ID of the package the contract was created from, if applicable. | | `rate_card_id` | `string` | The rate card ID of the contract | | `starting_at` | `timestamp` | The contract start timestamp (UTC) | | `ending_before` | `timestamp` | The contract end timestamp (UTC). This timestamp is exclusive. | | `archived_at` | `timestamp` | The timestamp (UTC) of when the contract was archived. | | `multiplier_override_prioritization` | `string` | The prioritization for a multiplier override. There are two options:
• Lowest multiplier (default): The lowest multiplier, aka the biggest discount, is used.
• Explicit: The override with the lowest priority will be prioritized. | | `net_payment_terms_days` | `integer` | The amount of time a customer has to pay a contract. For example, "net 30" | | `usage_statement_schedule_frequency` | `string` | The usage statement generation frequency. For example, "monthly" or "quarterly". | | `scheduled_charges_on_usage_invoices` | `string` | Valid values are `ALL` if scheduled invoices will be combined with usage invoices on the same date, otherwise null. | | `metadata` | [`Metadata`](/guides/reporting-insights/data-export/database-reference/#metadata) | JSON encoded object | | `created_at` | `timestamp` | The timestamp (UTC) of when the contract was created | | `created_by` | `string` | The entity the contract was created by | | `updated_at` | `timestamp` | The timestamp (UTC) at which this row was exported |
### `contracts_commits` The commits table only includes contract-level **commits**. It does not include customer-level commits or credits, or contract-level credits. | Column | Type | Description | | ------------------------------ | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `id` | `string` | The commit | | `environment_type` | `string` | The Metronome environment, `SANDBOX` or `PRODUCTION` | | `snapshot_id` | `string` | The snapshot ID of the row | | `contract_id` | `string` | The contract ID of the commit | | `amendment_id` | `string` | The amendment ID associated with the commit | | `type` | `string` | The type of commit: `postpaid` or `prepaid` | | `name` | `string` | The name of the commit | | `priority` | `float` | The priority that defines the order in which commits should be applied | | `description` | `string` | The description of the commit | | `product_id` | `string` | The product ID associated with the commit | | `amount` | `float` | Deprecated (use the amount from the schedule items instead) | | `access_schedule` | `json` | [`AccessSchedule`](/guides/reporting-insights/data-export/database-reference#contracts-commits-accessschedule) | | `invoice_schedule` | `json` | [`InvoiceSchedule`](/guides/reporting-insights/data-export/database-reference#contracts-commits-invoiceschedule) The `invoice_schedule` is always set for "postpaid" commits, sometimes set for "prepaid" commits, and never for "credit" | | `rollover_fraction` | `float` | The fraction of the commit that was rolled over | | `rate_type` | `string` | Either `COMMIT_RATE` or `LIST_RATE` | | `applicable_product_ids` | `json` | JSON encoded list of applicable product IDs | | `applicable_product_tags` | `json` | JSON encoded list of applicable product tags | | `specifiers` | `json` | [`CommitSpecifier[]`](/guides/reporting-insights/data-export/database-reference#contracts-commits-commitspecifier) - JSON encoded list of applicable usage | | `ledger` | `json` | [`CommitLedgerEntry[]`](/guides/reporting-insights/data-export/database-reference#contracts-commits-commitledgerentry) | | `rolled_over_from_commit_id` | `string` | The commit ID the commit was rolled over from | | `rolled_over_from_contract_id` | `string` | The contract ID the commit was rolled over from | | `recurring_commit_id` | `string` | The ID of the parent config that created this commit (null if this commit was not created by a recurring commit) | | `metadata` | `json` | [`Metadata`](/guides/reporting-insights/data-export/database-reference#metadata) | | `balance` | `float` | The current balance of the commit. This balance reflects the amount of commit that the customer has access to use at this moment. Expired and upcoming commit segments contribute 0 to the balance. The balance matches the sum of all ledger entries except when the sum of negative manual ledger entries exceeds the positive amount remaining on the commit. In that case, the balance is 0. All manual ledger entries associated with active commit segments are included in the balance, including future-dated manual ledger entries. | | `cost_basis` | `float` | The ratio of the amount paid for the commit to the amount of credit granted | | `updated_at` | `timestamp` | The timestamp (UTC) of when the commit was last updated | #### `contracts_commits.AccessSchedule` ```typescript theme={null} interface AccessSchedule { credit_type_id: string; credit_type_name: string; schedule_items: Array<{ id: string; /** ISO-8601 formatted timestamp */ date: string; /** ISO-8601 formatted timestamp */ end_date: string | null; /** Float */ amount: number; }>; } ``` #### `contracts_commits.InvoiceSchedule` ```typescript theme={null} interface InvoiceSchedule { credit_type_id: string; credit_type_name: string; do_not_invoice: boolean; schedule_items: Array<{ id: string; /** ISO-8601 formatted timestamp */ date: string; /** Float */ amount: number; invoice_id: string | null; }>; recurring_schedule: { /** ISO-8601 formatted timestamp */ start_date: string; /** ISO-8601 formatted timestamp */ end_date: string; /** Float */ amount: number; amount_distribution: "divided" | "divided_rounded" | "each"; frequency: "annual" | "monthly" | "quarterly" | "semi_annual"; /** Float */ quantity?: number; /** Float */ unit_price?: number; } | null; } ``` #### `contracts_commits.CommitLedgerEntry` ```typescript theme={null} type LedgerEntry = | { /** * Represents the starting balance of a postpaid commit. */ type: "postpaid_initial_balance"; /** ISO-8601 formatted timestamp */ timestamp: string; /** Float */ amount: number; } | { /** * Represents deductions from the remaining obligation of the * postpaid commit as the result of an invoice with usage that * applies to this commit. */ type: "postpaid_automated_invoice_deduction"; /** ISO-8601 formatted timestamp */ timestamp: string; /** Float */ amount: number; invoice_id: string; } | { /** * Represents a true-up invoice that was issued for this commit to * cover usage that was not covered by automated usage invoices. */ type: "postpaid_trueup"; /** ISO-8601 formatted timestamp */ timestamp: string; /** Float */ amount: number; invoice_id: string; } | { /** * Represents that a prepaid commit segment was started and the customer * now has access to the usage amount for that segment. These segments * are described in the access schedule of the prepaid commit. */ type: "prepaid_segment_start"; /** ISO-8601 formatted timestamp */ timestamp: string; /** Float */ amount: number; segment_id: string; } | { /** * Represents deductions from the prepaid commit segment caused by a * usage invoice that included usage applicable to this commit. */ type: "prepaid_automated_invoice_deduction"; /** ISO-8601 formatted timestamp */ timestamp: string; /** Float */ amount: number; segment_id: string; invoice_id: string; } | { /** * Represents unused usage from the prepaid commit which was rolled * over to a new contract. */ type: "prepaid_rollover"; /** ISO-8601 formatted timestamp */ timestamp: string; /** Float */ amount: number; segment_id: string; new_contract_id: string; new_commit_id: string; } | { type: "prepaid_commit_canceled"; /** ISO-8601 formatted timestamp */ timestamp: string; /** Float */ amount: number; segment_id: string; invoice_id: string; } | { type: "prepaid_commit_credited"; /** ISO-8601 formatted timestamp */ timestamp: string; /** Float */ amount: number; segment_id: string; invoice_id: string; } | { /** * Represents commit amount that was unused and expired at the end of * a commit segment. Does not include usage that rolled over to a new * contract. */ type: "prepaid_segment_expiration"; /** ISO-8601 formatted timestamp */ timestamp: string; /** Float */ amount: number; segment_id: string; } | { type: "prepaid_manual"; /** ISO-8601 formatted timestamp */ timestamp: string; /** Float */ amount: number; segment_id: string; reason: string; } | { type: "postpaid_manual"; /** ISO-8601 formatted timestamp */ timestamp: string; /** Float */ amount: number; }; ``` #### `contracts_commits.CommitSpecifier` ```typescript theme={null} type CommitSpecifier = { product_id?: string; product_tags?: string[]; presentation_group_values?: { [key: string]: string; }; pricing_group_values?: { [key: string]: string; }; } ``` ### `contracts_balances` | Column | Type | Description | | ------------------------------ | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `id` | `string` | The ID of the balance | | `environment_type` | `string` | The Metronome environment, `SANDBOX` or `PRODUCTION` | | `snapshot_id` | `string` | The snapshot ID of the row | | `customer_id` | `string` | The customer ID of the balance | | `contract_id` | `string` | The contract ID of the balance | | `amendment_id` | `string` | The amendment ID of the balance | | `type` | `string` | Either `postpaid`, `prepaid`, or `credit` | | `name` | `string` | The name of the balance | | `priority` | `float` | The priority that defines the order of balance application | | `description` | `string` | The description of the balance | | `product_id` | `string` | The product ID associated with the balance | | `access_schedule` | `json` | [`AccessSchedule`](/guides/reporting-insights/data-export/database-reference#contracts-balances-accessschedule) | | `invoice_schedule` | `json` | [`InvoiceSchedule`](/guides/reporting-insights/data-export/database-reference#contracts-balances-invoiceschedule) - The `invoice_schedule` is always set for "postpaid" commits, sometimes set for "prepaid" commits, and never for "credit" | | `rollover_fraction` | `float` | The fraction of the balance that was rolled over | | `rate_type` | `string` | Either `COMMIT_RATE` or `LIST_RATE` | | `applicable_product_ids` | `json` | JSON encoded list of applicable product IDs | | `applicable_product_tags` | `json` | JSON encoded list of applicable product tags | | `specifiers` | `json` | [`CommitSpecifier[]`](/guides/reporting-insights/data-export/database-reference#contracts-balances-commitspecifier) - JSON encoded list of applicable usage | | `applicable_contract_ids` | `json` | JSON encoded list of applicable contract IDs | | `invoice_contract_id` | `string` | The invoice contract ID associated with the balance | | `ledger` | `json` | [`CommitLedgerEntry[]`](/guides/reporting-insights/data-export/database-reference#contracts-balances-commitledgerentry) | | `rolled_over_from_commit_id` | `string` | The commit ID the balance was rolled over from | | `rolled_over_from_contract_id` | `string` | The contract ID the balance was rolled over from | | `recurring_commit_id` | `string` | The ID of the parent config that created this commit / credit (null if this commit was not created by a recurring commit / credit) | | `metadata` | `json` | [`Metadata`](/guides/reporting-insights/data-export/database-reference#metadata) | | `balance` | `float` | The current balance of the credit or commit. This balance reflects the amount of credit or commit that the customer has access to use at this moment. Expired and upcoming credit or commit segments contribute 0 to the balance. The balance matches the sum of all ledger entries except when the sum of negative manual ledger entries exceeds the positive amount remaining on the credit or commit. In that case, the balance is 0. All manual ledger entries associated with active credit or commit segments are included in the balance, including future-dated manual ledger entries. | | `cost_basis` | `float` | The ratio of the amount paid for the commit to the amount of credit granted | | `updated_at` | `timestamp` | The timestamp (UTC) at which this row was exported | #### `contracts_balances.AccessSchedule` ```typescript theme={null} interface AccessSchedule { credit_type_id: string; credit_type_name: string; schedule_items: Array<{ id: string; /** ISO-8601 formatted timestamp */ date: string; /** ISO-8601 formatted timestamp */ end_date: string | null; /** Float */ amount: number; }>; } ``` #### `contracts_balances.InvoiceSchedule` ```typescript theme={null} interface InvoiceSchedule { credit_type_id: string; credit_type_name: string; do_not_invoice: boolean; schedule_items: Array<{ id: string; /** ISO-8601 formatted timestamp */ date: string; /** Float */ amount: number; invoice_id: string | null; }>; recurring_schedule: { /** ISO-8601 formatted timestamp */ start_date: string; /** ISO-8601 formatted timestamp */ end_date: string; /** Float */ amount: number; amount_distribution: "divided" | "divided_rounded" | "each"; frequency: "annual" | "monthly" | "quarterly" | "semi_annual"; /** Float */ quantity?: number; /** Float */ unit_price?: number; } | null; } ``` #### `contracts_balances.CommitLedgerEntry` ```typescript theme={null} type LedgerEntry = | { /** * Represents the starting balance of a postpaid commit. */ type: "postpaid_initial_balance"; /** ISO-8601 formatted timestamp */ timestamp: string; /** Float */ amount: number; } | { /** * Represents deductions from the remaining obligation of the * postpaid commit as the result of an invoice with usage that * applies to this commit. */ type: "postpaid_automated_invoice_deduction"; /** ISO-8601 formatted timestamp */ timestamp: string; /** Float */ amount: number; invoice_id: string; } | { /** * Represents a true-up invoice that was issued for this commit to * cover usage that was not covered by automated usage invoices. */ type: "postpaid_trueup"; /** ISO-8601 formatted timestamp */ timestamp: string; /** Float */ amount: number; invoice_id: string; } | { /** * Represents that a prepaid commit segment was started and the customer * now has access to the usage amount for that segment. These segments * are described in the access schedule of the prepaid commit. */ type: "prepaid_segment_start"; /** ISO-8601 formatted timestamp */ timestamp: string; /** Float */ amount: number; segment_id: string; } | { /** * Represents deductions from the prepaid commit segment caused by a * usage invoice that included usage applicable to this commit. */ type: "prepaid_automated_invoice_deduction"; /** ISO-8601 formatted timestamp */ timestamp: string; /** Float */ amount: number; segment_id: string; invoice_id: string; } | { /** * Represents unused usage from the prepaid commit which was rolled * over to a new contract. */ type: "prepaid_rollover"; /** ISO-8601 formatted timestamp */ timestamp: string; /** Float */ amount: number; segment_id: string; new_contract_id: string; new_commit_id: string; } | { type: "prepaid_commit_canceled"; /** ISO-8601 formatted timestamp */ timestamp: string; /** Float */ amount: number; segment_id: string; invoice_id: string; } | { type: "prepaid_commit_credited"; /** ISO-8601 formatted timestamp */ timestamp: string; /** Float */ amount: number; segment_id: string; invoice_id: string; } | { /** * Represents commit amount that was unused and expired at the end of * a commit segment. Does not include usage that rolled over to a new * contract. */ type: "prepaid_segment_expiration"; /** ISO-8601 formatted timestamp */ timestamp: string; /** Float */ amount: number; segment_id: string; } | { type: "prepaid_manual"; /** ISO-8601 formatted timestamp */ timestamp: string; /** Float */ amount: number; segment_id: string; reason: string; } | { type: "postpaid_manual"; /** ISO-8601 formatted timestamp */ timestamp: string; /** Float */ amount: number; } | { /** * Represents that a credit segment was started and the customer * now has access to the usage amount for that segment. These segments * are described in the access schedule of the credit. */ type: "credit_segment_start"; /** ISO-8601 formatted timestamp */ timestamp: string; /** Float */ amount: number; segment_id: string; } | { /** * Represents deductions from the credit segment caused by a * usage invoice that included usage applicable to this credit. */ type: "credit_automated_invoice_deduction"; /** ISO-8601 formatted timestamp */ timestamp: string; /** Float */ amount: number; segment_id: string; invoice_id: string; } | { type: "credit_commit_canceled"; /** ISO-8601 formatted timestamp */ timestamp: string; /** Float */ amount: number; segment_id: string; invoice_id: string; } | { type: "credit_commit_credited"; /** ISO-8601 formatted timestamp */ timestamp: string; /** Float */ amount: number; segment_id: string; invoice_id: string; } | { /** * Represents credit amount that was unused and expired at the end of * a credit segment. */ type: "credit_segment_expiration"; /** ISO-8601 formatted timestamp */ timestamp: string; /** Float */ amount: number; segment_id: string; } | { type: "credit_manual"; /** ISO-8601 formatted timestamp */ timestamp: string; /** Float */ amount: number; segment_id: string; reason: string; }; ``` #### `contracts_balances.CommitSpecifier` ```typescript theme={null} type CommitSpecifier = { product_id?: string; product_tags?: string[]; presentation_group_values?: { [key: string]: string; }; pricing_group_values?: { [key: string]: string; }; } ``` This includes any recurring commits and credits that are defined on contracts. ### `contracts_recurring_commits_and_credits` | Column | Type | Description | | ------------------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `id` | `string` | The unique ID of the recurring commit/credit | | `environment_type` | `string` | The Metronome environment, `SANDBOX` or `PRODUCTION` | | `snapshot_id` | `string` | The snapshot ID of the row | | `contract_id` | `string` | The contract ID of the recurring commit/credit | | `customer_id` | `string` | The customer ID associated with the recurring commit/credit | | `type` | `string` | The type: `commit` or `credit` | | `name` | `string` | The name that's passed down to created commits/credits | | `priority` | `float` | The priority that's passed down to created commits/credits | | `description` | `string` | The description that's passed down to created commits/credits | | `product_id` | `string` | The product ID that's passed down to created commits/credits | | `access_amount` | `json` | [`AccessAmount`](/guides/reporting-insights/data-export/database-reference/#contracts_recurring_commits_and_credits-accessamount) | | `invoice_amount` | `json` | [`InvoiceAmount`](/guides/reporting-insights/data-export/database-reference/#contracts_recurring_commits_and_credits-invoiceamount) - Not set for recurring credits, but optional for recurring commits | | `rollover_fraction` | `float` | The rollover amount that's passed down to created commits/credits. Note that this controls rollover between contracts on contract transition, and not rollover from one period to the next. | | `rate_type` | `string` | The rate type that's passed down to created commits/credits | | `applicable_product_ids` | `json` | The applicable product IDs passed down to created commits/credits | | `applicable_product_tags` | `json` | The applicable product tags passed down to created commits/credits | | `specifiers` | `json` | [`CommitSpecifier[]`](/guides/reporting-insights/data-export/database-reference/#contracts_recurring_commits_and_credits-commitspecifier) - JSON encoded list of applicable usage | | `commit_duration` | `json` | [`CommitDuration`](/guides/reporting-insights/data-export/database-reference/#contracts_recurring_commits_and_credits-commitduration) How long each created commit is valid for starting from the start date. Currently the unit is always `PERIODS`, representing the length of the contract's billing periods (e.g. monthly, quarterly or annual) | | `proration` | `string` | Used to control whether the first or last billing periods are prorated. Valid values are `NONE`, `FIRST`, `LAST`, and `FIRST_AND_LAST`. Default is `FIRST_AND_LAST`. | | `proration_rounding` | `json` | [`ProrationRounding`](/guides/reporting-insights/data-export/database-reference/#contracts_recurring_commits_and_credits-prorationrounding) - Optional configuration for improved commit and invoice presentation. | | `recurrence_frequency` | `string` | If set, commits or credits are created based on the frequency specified and begin to recur at the start date specified on the recurring commit or credit config. Accepted values are `MONTHLY`, `QUARTERLY`, and `ANNUAL`. | | `metadata` | `json` | [`Metadata`](/guides/reporting-insights/data-export/database-reference/#metadata) | | `subscription_config` | `json` | [`SubscriptionConfig`](/guides/reporting-insights/data-export/database-reference/#contracts_recurring_commits_and_credits-subscriptionconfig) - Configuration for linked subscription | | `starting_at` | `timestamp` | The timestamp (UTC) of when the recurring credit or commit starts (inclusive) | | `ending_before` | `timestamp` | The timestamp (UTC) of when the recurring credit or commit ends (exclusive) | | `updated_at` | `timestamp` | The timestamp (UTC) of when the recurring commit / credit was last updated | #### `contracts_recurring_commits_and_credits.AccessAmount` ```typescript theme={null} interface AccessAmount { unit_price: number; quantity: number; credit_type_id: string; credit_type_name: string; } ``` #### `contracts_recurring_commits_and_credits.InvoiceAmount` ```typescript theme={null} interface InvoiceAmount { unit_price: number; quantity: number; credit_type_id: string; credit_type_name: string; } ``` #### `contracts_recurring_commits_and_credits.CommitSpecifier` ```typescript theme={null} type CommitSpecifier = { product_id?: string; product_tags?: string[]; presentation_group_values?: { [key: string]: string; }; pricing_group_values?: { [key: string]: string; }; } ``` #### `contracts_recurring_commits_and_credits.CommitDuration` ```typescript theme={null} enum CommitDurationUnit { PERIODS = "PERIODS", } interface CommitDuration { unit: CommitDurationUnit; value: number; } ``` #### `contracts_recurring_commits_and_credits.ProrationRounding` ```typescript theme={null} interface ProrationRounding { access: { rounding_method: "round_up" | "round_down" | "round_half_up"; decimal_places: number; }; invoice: { rounding_method: "round_up" | "round_down" | "round_half_up"; decimal_places: number; }; } ``` #### `contracts_recurring_commits_and_credits.SubscriptionConfig` ```typescript theme={null} enum SubscriptionAllocationForRecurringCommitEnum { POOLED = "pooled", INDIVIDUAL = "individual", } type SubscriptionConfig = { subscription_id: string; apply_seat_increase_config: { is_prorated: boolean; }; allocation: SubscriptionAllocationForRecurringCommitEnum; }; ``` Usage filters change over time, so each row represents a distinct version of a usage filter. To determine the correct version of a usage filter at a given point in time, filter the table by: * `contract_id` * `starting_at >= {TIME_PERIOD_START}` * `ending_before <= {TIME_PERIOD_END}` (Filter by all three qualifiers combined.) ### `contracts_usage_filter_schedule` | Column | Type | Description | | --------------- | ----------- | ------------------------------------------------------------------------------------ | | `id` | `string` | The Metronome ID of the contract usage filter | | `contract_id` | `string` | The ID of the contract associated with the usage filter | | `starting_at` | `timestamp` | The timestamp (UTC) of the starting timestamp the usage filter is active (inclusive) | | `ending_before` | `timestamp` | The timestamp (UTC) of the ending timestamp the usage filter is active (inclusive) | | `group_key` | `string` | The group key for the usage filter | | `group_values` | `json` | Group values for this usage filter row, stored in a JSON encoded list | | `metadata` | `json` | [`Metadata`](/guides/reporting-insights/data-export/database-reference/#metadata) | | `updated_at` | `timestamp` | The timestamp (UTC) at which this row was exported | ### `contracts_usage_filters` Usage filters change over time, so each row represents a distinct version of a usage filter. To determine the correct version of a usage filter at a given point in time: * Filter the table by `contract_id` and `starting_at <= {TIME}` * Select the row with the largest `version` | Column | Type | Description | | ------------------ | ----------- | ------------------------------------------------------------------------------------ | | `id` | `string` | The Metronome ID of the contract usage filter | | `environment_type` | `string` | The Metronome environment, `SANDBOX` or `PRODUCTION` | | `snapshot_id` | `string` | The ID of the snapshot this row was transferred during | | `contract_id` | `string` | The ID of the contract associated with the usage filter | | `version` | `integer` | The version of the usage filter | | `starting_at` | `timestamp` | The timestamp (UTC) of the starting timestamp the usage filter is active (inclusive) | | `group_key` | `string` | The group key for the usage filter | | `group_values` | `json` | Group values for this usage filter row, stored in a JSON encoded list | | `metadata` | `json` | [`Metadata`](/guides/reporting-insights/data-export/database-reference/#metadata) | | `updated_at` | `timestamp` | The timestamp (UTC) at which this row was exported | ### `contracts_prepaid_balance_threshold_configurations` | Column | Type | Description | | -------------------------------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | | `id` | `string` | Same as `contract_id` | | `environment_type` | `string` | The Metronome environment, `SANDBOX` or `PRODUCTION` | | `snapshot_id` | `string` | The snapshot ID for the row | | `contract_id` | `string` | The contract ID associated with the prepaid balance threshold configuration | | `enabled` | `boolean` | Whether prepaid balance threshold billing is enabled | | `threshold_amount` | `float` | The prepaid balance threshold at which to trigger threshold commit creation | | `recharge_to_amount` | `float` | The amount to recharge the balance to when the threshold is reached | | `commit_name` | `string` | The name to use as the line item of the threshold charge | | `commit_description` | `string` | The description used in the threshold commit | | `commit_product_id` | `string` | The fixed product ID used for prepaid balance threshold commits | | `commit_applicable_product_ids` | `json` | JSON encoded list of applicable product IDs for the commit | | `commit_applicable_product_tags` | `json` | JSON encoded list of applicable product tags for the commit | | `payment_gate_type` | `string` | The payment gate type: `STRIPE`, `EXTERNAL`, or `NONE` | | `tax_type` | `string` | The tax provider used: `STRIPE`, `ANROK`, `PRECALCULATED`, or `NONE` | | `stripe_payment_type` | `string` | The payment type if using Stripe payment gate: `PAYMENT_INTENT` or `INVOICE` | | `metadata` | `json` | [`Metadata`](/guides/reporting-insights/data-export/database-reference/#metadata) | | `updated_at` | `timestamp` | The timestamp (UTC) at which this row was exported | | `commit_duration_value` | `integer` | The numeric component of the commit duration, starting from the end of the invoice's service period. If not set, defaults to one year | | `commit_duration_unit` | `string` | The unit component of the commit duration: `DAYS`, `WEEKS`, `MONTHS`, or `YEARS`. If not set, defaults to one year | | `commit_rollover_fraction` | `float` | Fraction of the created commit's unused balance that will roll over on contract transitions. Between 0 and 1. If not set, defaults to 1 (100%) | | `commit_rate_type` | `string` | Either `COMMIT_RATE` or `LIST_RATE` | ### `contracts_spend_threshold_configurations` | Column | Type | Description | | --------------------- | ----------- | --------------------------------------------------------------------------------- | | `id` | `string` | Same as `contract_id` | | `environment_type` | `string` | The Metronome environment, `SANDBOX` or `PRODUCTION` | | `snapshot_id` | `string` | The snapshot ID for the row | | `contract_id` | `string` | The contract ID associated with the spend threshold configuration | | `enabled` | `boolean` | Whether spend threshold billing is enabled | | `threshold_amount` | `float` | The spend threshold at which to trigger threshold commit creation | | `commit_name` | `string` | The name to use as the line item of the threshold charge | | `commit_description` | `string` | The description used in the threshold commit | | `commit_product_id` | `string` | The ID of the fixed product used for spend threshold commits | | `payment_gate_type` | `string` | The payment gate type: `STRIPE`, `EXTERNAL`, or `NONE` | | `tax_type` | `string` | The tax provider used: `STRIPE`, `ANROK`, `PRECALCULATED`, or `NONE` | | `stripe_payment_type` | `string` | The payment type if using Stripe payment gate: `PAYMENT_INTENT` or `INVOICE` | | `metadata` | `json` | [`Metadata`](/guides/reporting-insights/data-export/database-reference/#metadata) | | `updated_at` | `timestamp` | The timestamp (UTC) at which this row was exported | ### `contracts_subscriptions` | Column | Type | Description | | ---------------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `id` | `string` | The ID of the subscription | | `environment_type` | `string` | The Metronome environment, `SANDBOX` or `PRODUCTION` | | `snapshot_id` | `string` | The snapshot ID for the row | | `customer_id` | `string` | The Metronome ID of the customer | | `contract_id` | `string` | The current contract ID | | `product_id` | `string` | The product ID of the subscription | | `name` | `string` | The name of the subscription | | `description` | `string` | The description of the subscription | | `billing_frequency` | `string` | The billing frequency of the subscription | | `billing_cycle_config` | `json` | [`BillingCycleConfig`](/guides/reporting-insights/data-export/database-reference/#contracts_subscriptions-billingcycleconfig) - Configuration for subscription billing and invoicing | | `collection_schedule` | `string` | The collection schedule of the subscription | | `is_prorated` | `boolean` | Whether or not the subscription is prorated | | `proration_rounding` | `json` | [`ProrationRounding`](/guides/reporting-insights/data-export/database-reference/#contracts_subscriptions-prorationrounding) - Optional configuration for improved invoice presentation. | | `invoice_behavior` | `string` | The invoice behavior of the subscription | | `quantity_schedule` | `json` | The quantity schedule of the subscription | | `fiat_credit_type_id` | `string` | The fiat credit type ID used by the subscription | | `metadata` | `json` | [`Metadata`](/guides/reporting-insights/data-export/database-reference/#metadata) | | `starting_at` | `timestamp` | The timestamp (UTC) of when the subscription starts | | `ending_before` | `timestamp` | The timestamp (UTC) of when the subscription ends | | `updated_at` | `timestamp` | The timestamp (UTC) at which this row was exported | #### `contracts_subscriptions.BillingCycleConfig` ```typescript theme={null} enum SubscriptionInvoicePlacementEnum { ON_USAGE_INVOICE = "ON_USAGE_INVOICE", ON_SCHEDULED_INVOICE = "ON_SCHEDULED_INVOICE", } interface BillingCycleConfig { anchor_date: timestamp; invoice_placement: SubscriptionInvoicePlacementEnum; } ``` #### `contracts_subscriptions.ProrationRounding` ```typescript theme={null} interface ProrationRounding { rounding_method: "round_up" | "round_down" | "round_half_up"; decimal_places: number; } ``` ### `contracts_scheduled_charges` | Column | Type | Description | | ------------------ | ----------- | ------------------------------------------------------------------------------------------------------------- | | `id` | `string` | The ID of the scheduled charge | | `environment_type` | `string` | The Metronome environment, `SANDBOX` or `PRODUCTION` | | `snapshot_id` | `string` | The snapshot ID for the row | | `contract_id` | `string` | The contract ID associated with the scheduled charge | | `amendment_id` | `string` | The amendment ID associated with the scheduled charge | | `name` | `string` | The name of the scheduled charge | | `description` | `string` | The description of the scheduled charge | | `product_id` | `string` | The product ID associated with the scheduled charge | | `credit_type_id` | `string` | The ID of the credit type or currency | | `credit_type_name` | `string` | The name of the credit type or currency | | `schedule` | `json` | [`Schedule`](/guides/reporting-insights/data-export/database-reference/#contracts-scheduled-charges-schedule) | | `metadata` | `json` | [`Metadata`](/guides/reporting-insights/data-export/database-reference/#metadata) | | `updated_at` | `timestamp` | The timestamp (UTC) at which this row was exported | #### `contracts_scheduled_charges.Schedule` ```typescript theme={null} interface Schedule { schedule_items: Array<{ id: string; /** ISO-8601 formatted timestamp */ date: string; /** Float */ amount: number; }>; recurring_schedule: { /** ISO-8601 formatted timestamp */ start_date: string; /** ISO-8601 formatted timestamp */ end_date: string; /** Float */ amount: number; amount_distribution: "divided" | "divided_rounded" | "each"; frequency: "annual" | "monthly" | "quarterly" | "semi_annual"; /** Float */ quantity?: number; /** Float */ unit_price?: number; } | null; } ``` ### `contract_hierarchy_configurations` | Column | Type | Description | | ---------------------------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------- | | `id` | `string` | Same as `contract_id` | | `contract_id` | `string` | The contract ID associated with the hierarchy configuration | | `parent_contract_id` | `string` | The ID of the parent contract in the hierarchy. Only populated for child contracts. | | `parent_customer_id` | `string` | The ID of the parent customer in the hierarchy. Only populated for child contracts. | | `child_info` | `json` | JSON encoded array of child contract information (each containing contract\_id and customer\_id). Only populated for parent contracts. | | `updated_at` | `timestamp` | The timestamp (UTC) at which this row was last updated | | `metadata` | `json` | [`Metadata`](/guides/reporting-insights/data-export/database-reference/#metadata) | | `environment_type` | `string` | The Metronome environment, `SANDBOX` or `PRODUCTION` | | `snapshot_id` | `string` | The snapshot ID for the row | | `payer` | `string` | The payer associated with the contract. Only populated for child contracts. | | `usage_statement_behavior` | `string` | The usage statement behavior configuration. Only populated for child contracts. | | `invoice_consolidation_type` | `string` | The type of invoice consolidation configured. Only populated for parent contracts. |
### Contract modifications Includes any modifications of contracts. The `contracts_overrides` table holds any overrides on top of an existing contract. The `contracts_transitions` and `contracts_edits` tables contain information about contracts ending, renewing, or changing. ### `contracts_overrides` | Column | Type | Description | | ------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------- | | `id` | `string` | The ID of the override | | `environment_type` | `string` | The Metronome environment, `SANDBOX` or `PRODUCTION` | | `snapshot_id` | `string` | The snapshot ID for the row | | `contract_id` | `string` | The contract ID of the override | | `amendment_id` | `string` | The amendment ID of the override | | `product_id` | `string` | The product ID of the override | | `entitled` | `boolean` | Whether or not the override is entitled | | `rate_type` | `string` | Either `multiplier`, `overwrite_flat`, or `overwrite_percentage`. `NULL` if this does not override the rate | | `multiplier` | `float` | The multiplier of the override | | `priority` | `float` | Only defined for contracts with EXPLICIT multiplier override prioritization | | `new_rate` | `json` | [`Rate`](/guides/reporting-insights/data-export/database-reference/#contracts-overrides-rate) | | `credit_type_id` | `string` | Only defined for "overwrite\_flat", "overwrite\_tiered", "overwrite\_subscription", or "overwrite\_custom" rate types | | `credit_type_name` | `string` | Only defined for "overwrite\_flat", "overwrite\_tiered", "overwrite\_subscription", or "overwrite\_custom" rate types | | `applicable_product_tags` | `json` | JSON encoded list of strings | | `override_specifiers` | `json` | [`OverrideSpecifier[]`](/guides/reporting-insights/data-export/database-reference/#contracts-overrides-overridespecifier) | | `target` | `string` | Either `COMMIT_RATE` or `LIST_RATE`. Indicates which rate the override applies to | | `is_commit_specific` | `boolean` | Whether or not the override is commit specific | | `metadata` | `json` | [`Metadata`](/guides/reporting-insights/data-export/database-reference/#metadata) | | `tiered_override` | `json` | Rates and tiers for tiered overrides | | `starting_at` | `timestamp` | The timestamp (UTC) of when the override starts (inclusive) | | `ending_before` | `timestamp` | The timestamp (UTC) of when the override ends (exclusive) | | `created_at` | `timestmap` | The timestamp (UTC) of when the override was created | | `updated_at` | `timestamp` | The timestamp (UTC) at which this row was exported | #### `contracts_overrides.OverrideSpecifier` ```typescript theme={null} type OverrideSpecifier = { commit_ids?: string[]; product_id?: string; product_tags?: string[]; pricing_group_values?: Array<{ name: string; value: string; }>; presentation_group_values?: Array<{ name: string; value: string; }>; // If set, the override will only apply to usage that burns down commits / credits that were created by the specified recurring config recurring_commit_ids?: string[]; any_commit_or_credit_ids?: string[]; }; ``` #### `contracts_overrides.Rate` ```typescript theme={null} type Rate = | { type: "flat"; unit_price: number; } | { type: "percentage"; fraction: number; use_list_prices: boolean; } | { type: "subscription"; unit_price: number; quantity: number; }; ``` ### `contracts_transitions` | Column | Type | Description | | ------------------ | ----------- | --------------------------------------------------------------------------------- | | `id` | `string` | The ID of the transition event | | `environment_type` | `string` | The Metronome environment, `SANDBOX` or `PRODUCTION` | | `snapshot_id` | `string` | The snapshot ID for the row | | `type` | `string` | The transition type, e.g. "renewal" | | `contract_id` | `string` | The current contract ID | | `from_contract_id` | `string` | The contract ID that applies prior to the transition | | `to_contract_id` | `string` | The contract ID that applies after the transition | | `date` | `timestamp` | The timestamp (UTC) of the transition | | `metadata` | `json` | [`Metadata`](/guides/reporting-insights/data-export/database-reference/#metadata) | | `updated_at` | `timestamp` | The timestamp (UTC) at which this row was exported | ### `contracts_edits` | Column | Type | Description | | ------------------ | ----------- | --------------------------------------------------------------------------------- | | `id` | `string` | The ID of the contract edit | | `contract_id` | `string` | The contract ID of the edit | | `timestamp` | `timestamp` | The timestamp (UTC) of the edit | | `edits` | `json` | Details of the edits made | | `metadata` | `json` | [`Metadata`](/guides/reporting-insights/data-export/database-reference/#metadata) | | `environment_type` | `string` | The Metronome environment, `SANDBOX` or `PRODUCTION` | | `created_by` | `string` | The entity the contract edit was created by | | `updated_at` | `timestamp` | The timestamp (UTC) at which this row was exported | | `snapshot_id` | `string` | The snapshot ID for the row | ### `contracts_amendments` | Column | Type | Description | | ------------------ | ----------- | --------------------------------------------------------------------------------- | | `id` | `string` | The ID of the contract amendment | | `environment_type` | `string` | The Metronome environment, `SANDBOX` or `PRODUCTION` | | `snapshot_id` | `string` | The snapshot ID for the row | | `contract_id` | `string` | The contract ID of the amendment | | `effective_at` | `timestamp` | The timestamp (UTC) of when the contract amendment is effective starting at | | `metadata` | `json` | [`Metadata`](/guides/reporting-insights/data-export/database-reference/#metadata) | | `created_at` | `timestamp` | The timestamp (UTC) of when the contract amendment was created | | `created_by` | `string` | The entity the contract amendment was created by | | `updated_at` | `timestamp` | The timestamp (UTC) at which this row was exported | ### Contract pricing Includes all information about pricing for a contract. ### `contracts_rate_cards` | Column | Type | Description | | ------------------------- | ----------- | -------------------------------------------------------------------------------- | | `id` | `string` | The Metronome contract rate card ID | | `environment_type` | `string` | The Metronome environment, `SANDBOX` or `PRODUCTION` | | `snapshot_id` | `string` | The ID of the snapshot this row was transferred during | | `credit_type_conversions` | `json` | The credit type conversions associated with the row | | `metadata` | `json` | [`Metadata`](/guides/reporting-insights/data-export/database-reference#metadata) | | `aliases` | `json` | List of aliases for the rate card | | `fiat_credit_type_id` | `string` | The fiat credit type ID associated with the rate card | | `fiat_credit_type_name` | `string` | The name of the fiat credit type associated with the rate card | | `description` | `string` | The description of the rate card | | `name` | `string` | The name of the rate card | | `created_by` | `string` | The creator of the rate card | | `created_at` | `timestamp` | The timestamp (UTC) this row was created | | `updated_at` | `timestamp` | The timestamp (UTC) this row was last updated | | `archived_at` | `timestamp` | The timestmap (UTC) this row was archived if applicable | ### `contracts_rate_card_entries` | Column | Type | Description | | ---------------------- | ----------- | -------------------------------------------------------------------------------- | | `id` | `string` | The Metronome contract rate card entry ID | | `environment_type` | `string` | The Metronome environment, `SANDBOX` or `PRODUCTION` | | `rate_card_id` | `string` | The Metronome rate card ID associated with this entry | | `product_id` | `string` | The product ID associated with this entry | | `version` | `integer` | The version of this rate card entry | | `entitled` | `boolean` | Whether or not the entry is entitled | | `rate` | `string` | The rate that applies to the entry | | `commit_rate` | `string` | The commit rate that applies to the entry (if applicable) | | `product_order` | `integer` | The product order associated with the entry | | `pricing_group_values` | `json` | The pricing group values that apply to the entry | | `snapshot_id` | `string` | The ID of the snapshot this row was transferred during | | `metadata` | `json` | [`Metadata`](/guides/reporting-insights/data-export/database-reference#metadata) | | `credit_type_id` | `string` | The credit type ID associated with the rate card | | `credit_type_name` | `string` | The name of the credit type associated with the rate card | | `billing_frequency` | `string` | The billing frequency associated with the entry. For subscriptions only. | | `starting_at` | `timestamp` | The timestamp (UTC) the rate card entry starts at (inclusive) | | `ending_before` | `timestamp` | The timestamp (UTC) the rate card entry ends at (exclusive) | | `updated_at` | `timestamp` | The timestamp (UTC) this row was last updated | ### `contracts_product_list_item_versions` | Column | Type | Description | | ------------------------- | ----------- | ---------------------------------------------------------------------------------------------- | | `id` | `string` | The Metronome product list item version ID | | `environment_type` | `string` | The Metronome environment, `SANDBOX` or `PRODUCTION` | | `snapshot_id` | `string` | The ID of the snapshot this row was transferred during | | `product_list_item_id` | `string` | The product list item ID associated with the row | | `type` | `string` | The type of the product list item version | | `version` | `integer` | The version of the product list item | | `name` | `string` | The name of the product list item version | | `is_refundable` | `boolean` | Whether or not the product list item version is refundable | | `billable_metric_id` | `string` | The billable metric ID associated with the product list item version | | `composite_product_ids` | `json` | The list of composite product IDs associated with the row | | `composite_scope` | `string` | The scope of the composite product, `CONTRACT` or `CUSTOMER` | | `tags` | `json` | The list of tags associated with the row | | `composite_tags` | `json` | The list of composite tags associated with the row | | `include_composite_spend` | `boolean` | Whether or not the composite product is allowed to include spend from other composite products | | `quantity_conversion` | `json` | The quantity conversion for the row | | `quantity_rounding` | `json` | The quantity rounding for the row | | `pricing_group_key` | `json` | The pricing group key for the row | | `presentation_group_key` | `json` | The presentation group key for the row | | `metadata` | `json` | [`Metadata`](/guides/reporting-insights/data-export/database-reference/#metadata) | | `starting_at` | `timestamp` | The timestamp (UTC) the version is active starting at (inclusive) | | `created_at` | `timestamp` | The timestamp (UTC) this row was created at | | `created_by` | `string` | The entity this row was created by | | `updated_at` | `timestamp` | The timestamp (UTC) this row was last updated | ## Packages Includes information related to packages. ### `packages` | Column | Type | Description | | ------------------------------------- | ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `id` | `string` | ID of the package | | `name` | `string` | Name of the package | | `rate_card_id` | `string` | The ID of the rate card used on the package | | `duration_unit` | `string` | The unit of the package duration. Available values are `DAYS`, `WEEKS`, `MONTHS`, `YEARS` | | `duration_value` | `integer` | The value of the package duration. `duration_unit` + `duration_value` represent the length of the package | | `multiplier_override_prioritization` | `string` | The prioritization for a multiplier override. There are two options:
  • Lowest multiplier (default): The lowest multiplier, aka the biggest discount, is used.
  • Explicit: The override with the lowest priority will be prioritized.
| | `net_payment_terms_days` | `integer` | The amount of time a customer has to pay a contract. For example, “net 30" | | `usage_statement_schedule_frequency` | `string` | The usage statement generation frequency. For example, “monthly” or “quarterly”. | | `scheduled_charges_on_usage_invoices` | `string` | Valid values are `ALL` if scheduled invoices will be combined with usage invoices on the same date, otherwise null. | | `billing_provider` | `string` | The billing provider used on a contract created from the package. | | `delivery_method` | `string` | The delivery method used on a contract created from the package. | | `aliases` | `json` | List of scheduled aliases for the package | | `created_at` | `timestamp` | The timestamp (UTC) of when the package was created | | `created_by` | `string` | The entity the package was created by | | `archived_at` | `timestamp` | The timestamp (UTC) of when the package was archived | | `updated_at` | `timestamp` | The timestamp (UTC) at which this row was exported | | `environment_type` | `string` | The Metronome environment, `SANDBOX` or `PRODUCTION` | | `snapshot_id` | `string` | The snapshot ID for the contract row | | `metadata` | [`Metadata`](#metadata) | JSON encoded object |
## Payments **Private Beta** Metronome invoicing is currently in Private Beta. Contact us via the [Metronome support portal](https://support.metronome.com/) for early access. Payment information when invoicing with Metronome. ### `payment` | Column | Type | Description | | ------------------ | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `id` | `string` | The ID of the payment | | `invoice_id` | `string` | The invoice ID associated with the payment | | `customer_id` | `string` | The customer ID associated with the payment | | `contract_id` | `string` | The contract ID associated with the payment | | `environment_type` | `string` | The Metronome environment, `SANDBOX` or `PRODUCTION` | | `amount` | `decimal` | The total amount of the payment | | `amount_paid` | `decimal` | The amount that has been paid; equals `amount` if status is `PAID`, otherwise `0` | | `credit_type_id` | `string` | The credit type ID (fiat currency) for the payment | | `credit_type_name` | `string` | The name of the credit type associated with the payment | | `status` | `string` | The status of the payment | | `error_message` | `string` | Error message from the payment provider, if applicable | | `payment_gateway` | `json` | [`PaymentGateway`](/guides/reporting-insights/data-export/database-reference/#payment-paymentgateway) - Payment gateway details (e.g., Stripe payment intent and method information) | | `created_at` | `timestamp` | The timestamp (UTC) of when the payment was created | | `updated_at` | `timestamp` | The timestamp (UTC) of when the payment was last updated | #### `payment.PaymentGateway` ```typescript theme={null} type PaymentGateway = { type: "stripe"; stripe: { payment_intent_id: string; payment_method_id: string; error: string | null; }; } | null; ``` ## Alerts Includes alerts and the history of customer alerts triggered. ### `alert` | Column | Type | Description | | ------------------ | ----------- | -------------------------------------------------------------------------------------------------------- | | `id` | `string` | The ID of the alert | | `name` | `string` | The name of the alert | | `alert_type` | `string` | The type of alert | | `threshold` | `decimal` | The threshold to trigger the alert | | `webhooks_enabled` | `boolean` | Indicates if the alert is configured for webhooks | | `environment_type` | `string` | The Metronome environment, `SANDBOX` or `PRODUCTION` | | `created_at` | `timestamp` | The timestamp (UTC) of when the alert was created | | `disabled_at` | `timestamp` | The timestamp (UTC) of when the alert was disabled | | `updated_at` | `timestamp` | The timestamp (UTC) of when the alert was last updated | | `archived_at` | `timestamp` | The timestamp (UTC) of when the alert was archived | | `group_values` | `json` | The group value filters associated with the alert. Only present for `spend_threshold_reached` alerts. | | `seat_filter` | `json` | The seat filter associated with the alert. Only present for `low_remaining_seat_balance_reached` alerts. | | `customer_id` | `string` | The customer ID associated with the alert. If null, the configured alert applies to all customers. | ### `customer_alert_history` | Column | Type | Description | | ------------------ | ----------- | ------------------------------------------------------------------- | | `id` | `string` | The Metronome ID of the customer alert history | | `environment_type` | `string` | The Metronome environment, `SANDBOX` or `PRODUCTION` | | `customer_id` | `string` | The name of the customer associated with the alert history | | `alert_id` | `string` | The alert ID associated with the row | | `alert_status` | `string` | The alert status associated with the row | | `additional_data` | `json` | Additional data about the alert | | `created_at` | `timestamp` | Timestamp (UTC) when the alert was evaluated and the status changed | ## Metadata Many tables in the data export include a `metadata` column. Clients using Metronome have a variety of external systems and require different metadata to be stored. This metadata is client-specific and is stored as a JSON object in the `metadata` column of the table. # Overview Source: https://docs.metronome.com/guides/reporting-insights/data-export/overview Metronome can send your sandbox and production data directly to your data warehouse, giving you the flexibility to build reports and dashboards with your favorite data tools. Exporting data from Metronome is a simple process requiring a one-time setup of your data destination at [https://app.metronome.com/developer/data-export](https://app.metronome.com/developer/data-export). After the initial export, your data is updated automatically at least once a day (depending on the table). **GET STARTED** To set up your destination data warehouse, contact [solutions@metronome.com](mailto:solutions@metronome.com). ## Supported destination types Metronome supports data export to the most common data warehouses, databases, and object storage providers. We continue to add new providers; if your preferred vendor is not listed below, contact [solutions@metronome.com](mailto:solutions@metronome.com). **ONE DESTINATION LIMIT** Only a single destination for data exports can be configured across all Metronome environments. Distinct destinations cannot be set up for Production and Sandbox. ### Data warehouse * [BigQuery](/guides/reporting-insights/data-export/destinations/bigquery) * [Clickhouse](/guides/reporting-insights/data-export/destinations/clickhouse) * [Databricks](/guides/reporting-insights/data-export/destinations/databricks) * Delta Lake * [Redshift](/guides/reporting-insights/data-export/destinations/redshift) * Redshift Serverless * [Snowflake](/guides/reporting-insights/data-export/destinations/snowflake) ### Database * [Athena](/guides/reporting-insights/data-export/destinations/athena) * MongoDB * [MySQL](/guides/reporting-insights/data-export/destinations/mysql-generic) * [MySQL Aurora](/guides/reporting-insights/data-export/destinations/mysql-aurora) * Oracle * PlanetScale * [Postgres](/guides/reporting-insights/data-export/destinations/postgres-generic) * [Postgres (AWS)](/guides/reporting-insights/data-export/destinations/postgres-aws) * [SingleStore](https://docs.singlestore.com/) * SQL Server ### Object storage * [Azure Blob Storage](/guides/reporting-insights/data-export/destinations/staging-abs) * [Google Cloud Storage](/guides/reporting-insights/data-export/destinations/gcs) * [S3](/guides/reporting-insights/data-export/destinations/s3) * [S3 Compatible](/guides/reporting-insights/data-export/destinations/s3-compatible) * SFTP **Folder structure:** ``` ///dt=/_.parquet ``` **Path components:** | Component | Description | | ---------------------- | ---------------------------------------------------------------------- | | `` | Your configured bucket name | | `` | Your configured folder path | | `` | Table being transferred (e.g., `invoice`, `customer`) | | `` | Transfer date in `YYYY-MM-DD` format (e.g., `2025-01-01`) | | `` | Transfer timestamp in `YYYYMMDDHHmmss` format (e.g., `20250102150405`) | | `` | Monotonically increasing integer (no special meaning) | **APPEND-ONLY** Object storage destinations listed above export files as an append-only log with at-least-once semantics. There will be rows with the same primary key in multiple files because of updates to the row or transfer retries. Metronome customers need to handle these appropriately by using the most recent data for each row. ### Other * [Google Sheets](/guides/reporting-insights/data-export/destinations/sheets) ## Data availability Metronome can export these types of sandbox and production data: | Metronome data | Table name | Transfer Frequency† | Average Freshness†† | Table Type | | ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------- | ------------------- | ----------- | | Billable Metrics | [billable\_metric](/guides/reporting-insights/data-export/database-reference#billable-metric) | 2 hours | 4 hours | Incremental | | Credit Type | [credit\_type](/guides/reporting-insights/data-export/database-reference#credit-type) | 2 hours | 4 hours | Incremental | | Events | [events](/guides/reporting-insights/data-export/database-reference#events) | 2 hours | 4 hours | Incremental | | Customers | [customer](/guides/reporting-insights/data-export/database-reference#customer) | 2 hours | 4 hours | Incremental | | Finalized Invoices | [invoice](/guides/reporting-insights/data-export/database-reference#invoice) | 2 hours | 4 hours | Incremental | | Finalized Invoices | [line\_item](/guides/reporting-insights/data-export/database-reference#line-item) | 2 hours | 4 hours | Incremental | | Draft Invoices | [draft\_invoice](/guides/reporting-insights/data-export/database-reference#draft-invoice) | 24 hours | 24 hours | Snapshot | | Draft Invoices | [draft\_line\_item](/guides/reporting-insights/data-export/database-reference#draft-line-item) | 24 hours | 24 hours | Snapshot | | Invoice Breakdowns | [breakdowns\_invoices](/guides/reporting-insights/data-export/database-reference#breakdowns-invoices) | 24 hours | 24 hours | Incremental | | Invoice Breakdowns | [breakdowns\_line\_items](/guides/reporting-insights/data-export/database-reference#breakdowns-line-items) | 24 hours | 24 hours | Incremental | | Invoice Breakdowns | [breakdowns\_draft\_invoices](/guides/reporting-insights/data-export/database-reference#breakdowns-draft-invoices) | 24 hours | 24 hours | Snapshot | | Invoice Breakdowns | [breakdowns\_draft\_line\_items](/guides/reporting-insights/data-export/database-reference#breakdowns-draft-line-items) | 24 hours | 24 hours | Snapshot | | Contracts | [contracts\_contracts](/guides/reporting-insights/data-export/database-reference#contracts-contracts) | 24 hours | 24 hours | Snapshot | | Contracts | [contracts\_commits](/guides/reporting-insights/data-export/database-reference#contracts-commits) | 24 hours | 24 hours | Snapshot | | Contracts | [contracts\_balances](/guides/reporting-insights/data-export/database-reference#contracts-balances) | 24 hours | 24 hours | Snapshot | | Contracts | [contracts\_recurring\_commits\_and\_credits](/guides/reporting-insights/data-export/database-reference#contracts-recurring-commits-and-credits) | 24 hours | 24 hours | Snapshot | | Contracts | [contracts\_subscriptions](/guides/reporting-insights/data-export/database-reference#contracts-subscriptions) | 24 hours | 24 hours | Snapshot | | Contracts | [contracts\_scheduled\_charges](/guides/reporting-insights/data-export/database-reference#contracts-scheduled-charges) | 24 hours | 24 hours | Snapshot | | Contracts | [contracts\_usage\_filter\_schedule](/guides/reporting-insights/data-export/database-reference#contracts-usage-filter-schedule) | 24 hours | 24 hours | Snapshot | | Contracts | [contracts\_usage\_filters](/guides/reporting-insights/data-export/database-reference#contracts-usage-filters) | 24 hours | 24 hours | Snapshot | | Contracts | [contracts\_prepaid\_balance\_threshold\_configurations](/guides/reporting-insights/data-export/database-reference#contracts-prepaid-balance-threshold-configurations) | 24 hours | 24 hours | Snapshot | | Contracts | [contracts\_spend\_threshold\_configurations](/guides/reporting-insights/data-export/database-reference#contracts-spend-threshold-configurations) | 24 hours | 24 hours | Snapshot | | Contract Modifications | [contracts\_overrides](/guides/reporting-insights/data-export/database-reference#contracts-overrides) | 24 hours | 24 hours | Snapshot | | Contract Modifications | [contracts\_transitions](/guides/reporting-insights/data-export/database-reference#contracts-transitions) | 24 hours | 24 hours | Snapshot | | Contract Modifications | [contracts\_edits](/guides/reporting-insights/data-export/database-reference#contracts-edits) | 24 hours | 24 hours | Snapshot | | Contract Modifications | [contracts\_amendments](/guides/reporting-insights/data-export/database-reference#contracts-amendments) | 24 hours | 24 hours | Snapshot | | Contract Pricing | [contracts\_rate\_cards](/guides/reporting-insights/data-export/database-reference#contracts-rate-cards) | 24 hours | 24 hours | Snapshot | | Contract Pricing | [contracts\_rate\_card\_entries](/guides/reporting-insights/data-export/database-reference#contracts-rate-card-entries) | 24 hours | 24 hours | Snapshot | | Contract Pricing | [contracts\_product\_list\_item\_versions](/guides/reporting-insights/data-export/database-reference#contracts-product-list-item-versions) | 24 hours | 24 hours | Snapshot | | Packages | [packages](/guides/reporting-insights/data-export/database-reference#packages) | 24 hours | 24 hours | Snapshot | | Alerts | [alert](/guides/reporting-insights/data-export/database-reference#alert) | 2 hours | 4 hours | Incremental | | Alerts | [customer\_alert\_history](/guides/reporting-insights/data-export/database-reference#customer-alert-history) | 2 hours | 4 hours | Incremental | † Transfer frequency indicates the frequency at which new records get sent to your destination. †† Average Freshness indicates the average delay between when data is generated in Metronome and when the data appears in your destination. **INCREMENTAL DATA EXPORTS** Data exports of incremental tables contain only the rows of data that have changed since the last export. Use the `updated_at` column to pull the latest updates. # ASC 606 revenue recognition guide for usage companies Source: https://docs.metronome.com/guides/reporting-insights/financial-reporting/asc-606-revenue-recognition This guide explains U.S. GAAP's ASC 606 Revenue from Contracts with Customers in practical terms and helps illustrate how each step of the standard connects to Metronome's data model and product features. Our goal is to ensure every product decision, from data schema design to reporting output, supports customers' ability to comply with ASC 606 with minimal manual work. Metronome directly impacts your ability to comply with ASC 606 because: * We capture usage and billing data that feed into your revenue recognition process * Our ability to map charges to obligations, track contract changes, and provide granular event data makes us a key system of record * By mapping our data structure to ASC 606, we eliminate manual steps for you and better align our platform with your needs **Disclaimer** This guide is provided for informational purposes only. While Metronome provides data, reporting, and system capabilities that can support you in applying revenue recognition principles, Metronome itself is not a revenue recognition platform and does not generate revenue journal entries or make accounting determinations. Revenue recognition outcomes depend on your specific contracts, policies, and interpretations of accounting standards. The examples and scenarios described in this guide are intended to illustrate how Metronome's features and data may be used, but they should not be taken as prescriptive guidance. You are solely responsible for determining and applying your revenue recognition policies. Metronome recommends that you consult with qualified accounting and revenue recognition professionals to ensure compliance with applicable standards. ## Data model and reporting principles for ASC 606 Metronome is purpose-built to serve the needs of modern, usage-based, and hybrid SaaS businesses. It goes beyond traditional billing engines by providing real-time infrastructure, fine-grained data models, and flexible commercial constructs—all of which support scalable and compliant revenue recognition under ASC 606. To support the revenue recognition process, our platform follows these principles: ### Comprehensive data Metronome provides the raw and structured data needed to manage complex revenue recognition and support audit-ready reporting and analytics. This data includes: * Full transaction history and ledger-level entries * Daily granularity of usage and service delivery * Breakdowns by product, customer, commitment, and revenue category ### Granularity and period-specific data Metronome captures detailed transaction history and ledgers with daily granularity down to products and revenue categories, including: * Tracking prepaid commits, postpaid draws and true-ups * Free credits or promotional discounts This allows for period-specific, detailed data essential for revenue recognition and audit support. ### Comprehensive contract and pricing management Metronome maintains a centralized contract object containing pricing, terms, product access, commitments, credits, and billing schedules, with flexible rate structures and preserved version history. Metronome encodes each deal through flexible, contract-based modeling and supports pricing models such as: * Pay-as-you-go * Prepaid usage commitments * Subscriptions with usage-based overage * Enterprise credits with tiered pricing * Bundled or hybrid pricing structures * Seats and seats with overages pricing models ### Clear product and obligation tagging Stable identifiers and explicit categorization of revenue types (point-in-time vs over-time) are kept to assist with allocation and recognition rules. Stable identifiers allow you to automate allocation and recognition rules in ERP tools and avoid manual remapping when historical data is re-pulled. ### Real-time usage processing and invoices The platform is engineered for high-volume, real-time environments, capable of: * Ingesting billions of usage events via APIs * Processing events through billable metrics * Applying pricing and discounts dynamically * Issuing invoices or updating balances instantly This real-time flow is critical for fraud detection, spend throttling, and usage enforcement, helping companies reduce exposure to uncollectible revenue. ### Traceable data and audit trail Every billed amount links back to original usage, applied rate, and adjustments, with consistent tags and an immutable audit trail. All changes to contracts, pricing, or obligation tagging are captured with version history which ensures transparency, prevents retroactive data inconsistencies, and builds trust in Metronome's outputs as a reliable system of record. ### Robust reporting and integration Flexible reporting with product/SKU-level detail, schema-stable exports, and APIs for seamless ERP/revenue tool integration. Reporting allows for cross-system reconciliation, including: * API and data warehouse integrations * Detailed exports of line items, ledgers and balances * Reconciliations with systems such as Salesforce, Stripe, ERPs, and customer data warehouses ### Forecasting and breakage insights Ability to track and estimate unused commitments and credit rollovers for future revenue impact analysis. ## The five-step ASC 606 model The standard requires companies to follow this sequence: 1. Identify the contract(s) with a customer 2. Identify the performance obligations in the contract 3. Determine the transaction price 4. Allocate the transaction price to the performance obligations 5. Recognize revenue when (or as) the obligations are satisfied Each step below includes: * What ASC 606 requires * Customer challenges * How Metronome supports this step * Critical Callouts / Common Issues ## Step 1: Identify the contract ### Accounting meaning A contract is a legally enforceable agreement with a customer with defined rights, obligations, and payment terms. For revenue recognition, every usage event, charge, or credit in Metronome must tie back to a specific contract with a customer, as the contract is the basis for all subsequent ASC 606 steps. Customers may have multiple contracts with one company (e.g., a master agreement and separate orders) that need separate tracking. In addition, contracts can change over time, through extensions, renewals, scope increases, rate changes, which can trigger new accounting assessments. ### Customer challenges * Linking billing data back to the correct contract * Tracking contract start/end dates and changes over time * Maintaining an audit trail for contract amendments ### How Metronome supports * **Unique contract ID field** in all relevant data exports and API calls * **Key contract data capture** including start and end dates, effective dates for amendments and total contract value (TCV) * **Store version history** to retain contract amendments without overwriting historical data * **Support contract hierarchy** to provide linkage of contracts (treat multiple related agreements as one contract from an accounting perspective) if needed * **Integration hooks** to CRM/ERP contract records so finance can reconcile **Key product focus:** Ensure all usage, billing, and adjustment data is tied to a persistent, unique Contract ID. ### Helpful links to learn more * **[How Metronome works - Contracts: Encode Your Commercial Model](/guides/get-started/how-metronome-works#contracts%3A-encode-your-commercial-model%E2%80%8B):** This section explains that Metronome uses contracts to connect customers to pricing structures and define specific commercial arrangements, including base pricing, custom terms, product access, payment structures, and billing cycles. * **[Reconcile data - Contract Reconciliation](/guides/reporting-insights/financial-reporting/reconcile-data#contract-reconciliation):** This section details how Metronome data, including contract start and end dates, commit amounts, and custom negotiated discounts, can be reconciled against Salesforce CPQ to ensure accuracy. To support this reconciliation, you will need to add the relevant SFDC object ids to each Metronome object using custom fields. You can also use the [Metronome to Salesforce integration](/integrations/platform-integrations/sfdc-integration) to automatically export `metronome__Contract__c` and `metronome__Commit__c` data objects into Salesforce which contain contract ID, customer, rate card, name, start/end dates, and usage statement schedule frequency, as well as commit details like type, priority, total amount, and current balance. * **[Revenue recognition examples](/guides/reporting-insights/financial-reporting/revenue-recognition-examples):** This section includes example tables for Customer and Contract data, demonstrating how contract IDs, customer IDs, and start/end dates are populated for various revenue reporting scenarios. ### Critical callouts / Common issues #### Multiple agreements = One contract Under ASC 606, contracts signed close together with a single commercial objective may need to be combined. Metronome clients sometimes fail to link related contracts in Metronome. Metronome supports the linkage of related contracts through its parent-child account linkage feature, in which multiple contract IDs can be linked together. **Example:** A SaaS provider (company) executes a three-year subscription agreement and at or near the same time, also executes a separate professional services SOW to assist in implementing its platform. Because these agreements were likely negotiated together as part of one commercial package, ASC 606 may require combining them into a single contract for revenue recognition purposes. In Metronome, users have the ability to link these accounts as parent-child relationships; otherwise these will show as separate customer contracts. #### Contract modifications Upsells, downgrades, and renewals require careful accounting treatment (prospective vs. retrospective). Metronome can track modifications and maintain version history and an audit trail for such amendments, but you must ultimately decide how to treat them under ASC 606. **Example:** A SaaS provider (company) has a customer on a \$100k/year subscription that upgrades mid-term to add \$40k/year of additional functionality. The company must determine if this is a separate contract (prospective accounting) or a modification of the original contract (retrospective catch-up). Metronome can capture and track the change, but the company still needs to apply the correct ASC 606 treatment. #### Opt-out clauses and termination rights Multi-year deals with opt-outs may not count as one multi-year contract. Metronome clients may incorrectly report TCV without considering the enforceable contract period under ASC 606. **Example:** A SaaS provider (company) signs what appears to be a three-year, \$300k deal. However, the customer can terminate after the first year with no penalty. For ASC 606 purposes, only the first year (\$100k) is enforceable. If the company reports \$300k TCV without considering the opt-out, they are overstating revenue expectations. Metronome can flag these terms, but the accounting conclusion must be made by the client. #### Committed "free" periods Metronome clients often neglect to include committed "free" periods in the contract definition, leading to mismatches between system usage and revenue recognition. **Example:** A SaaS provider (company) offers a 12-month contract with a 2-month "free" period at the start, followed by 10 months of paid service at \$10k/month. The enforceable contract period is still 12 months, with \$100k in total consideration, but companies sometimes only record 10 months. This creates a mismatch between usage data in Metronome (12 months of service) and the revenue contract (12 months, \$100k). Correctly setting this up avoids gaps in recognition and reporting. ## Step 2: Identify the performance obligations ### Accounting meaning Performance obligations are distinct (separable) promises to deliver goods or services; in any contract with a customer there can be single obligations (e.g., a year of platform access) or multiple obligations (e.g., subscription plus implementation services plus add-ons). Identifying performance obligations is important because each obligation may be accounted for separately under ASC 606. In SaaS and usage-based revenue models, performance obligations might be: * Platform access (subscription) * Usage-based services (API calls, data processed) * Implementation/setup * Enhanced support ### Customer challenges * Disaggregating or combining charges into clear performance obligations (i.e., mapping) * Handling bundled offerings without losing line-level detail ### How Metronome supports * **Product and rate card structure** allows mapping SKUs/usage metrics to specific obligation categories or obligation ID * **Obligation tags** in the data model to flag each charge or usage event * **Bundle support** while retaining disaggregated product-level exports * **Ability to retroactively tag** historical data if obligations change **Key product focus:** Provide customers with obligation-level granularity in all outputs, which is essential for allocation and revenue rules. ### Mapping to Metronome's current documentation * **[How Metronome works - Products & Rate Cards section](/guides/get-started/how-metronome-works#price%3A-products-%26-rate-cards%E2%80%8B):** This section describes Products as what is being sold to customers (individual SKUs that appear as line items on invoices) and mentions support for various product types, including usage-based, fixed, or subscription charges. This directly relates to defining performance obligations. It also notes the ability to customize invoice appearance, organize related SKUs with tags, and control granularity. * **[How revenue recognition works - Revenue reporting categories subsection](/guides/reporting-insights/financial-reporting/revenue-recognition#revenue-reporting-categories):** This section lists common revenue reporting categories such as on-demand usage, prepaid/postpaid commitment drawdown, overage usage, and credit drawdown, further broken down by product, which aligns with identifying distinct performance obligations. * **[Sync into Salesforce](/integrations/platform-integrations/sfdc-integration):** The `metronome__Invoice_Line_Item__c` data object, which includes `Product_Type__c`, helps track what specific products are being invoiced, supporting the identification of performance obligations. ### Critical callouts / Common issues #### Complexity in identifying performance obligations What appears to be a distinct SKU in Metronome may not always be a separate performance obligation under ASC 606. Or vice versa, as in the case of a hybrid model, such as usage plus subscription services, which may need to be separated into distinct performance obligations. Misclassifying SKUs, e.g., treating everything as stand-alone or failing to separate hybrid models, can lead to revenue recognition errors. Metronome allows mapping SKUs and usage metrics to specific obligation categories or IDs, but user is responsible for setting this up and mapping correctly. **Example:** A SaaS provider (company) includes "Premium Analytics" as a separate SKU in Metronome. In practice, this feature is integrated into the core subscription and not distinct on its own. If treated as a separate performance obligation, the company may allocate revenue incorrectly. Conversely, another company bundles "free" implementation services into the core subscription without breaking them out as a separate SKU. If those services are distinct under ASC 606, failing to separate them leads to incorrect revenue recognition. Both scenarios highlight the risk of misclassifying SKUs in Metronome and the importance of properly evaluating performance obligations beyond system configuration. #### Implementation / setup fees One-time charges must be evaluated; are they distinct services or part of a broader service obligation? Once determined, users can then map such services to their specific obligation within Metronome (e.g., either as combined or as a separate obligation ID). **Example:** The customer of a SaaS provider (company) pays a \$20k onboarding fee plus \$100k for the annual software subscription. If the onboarding activities do not transfer a distinct good or service (e.g., they only enable the customer to access the subscription), the \$20k is likely not a separate performance obligation and in such case would be deferred and recognized over the subscription term (i.e., combined with the subscription). #### Support and service tiers Customers may combine support activities with the core platform services, but certain support offerings may require it to be assessed separately as a performance obligation and mapped to their own obligation ID. **Example:** A SaaS provider (company) includes "24/7 Premium Support" as an add-on support service. Some companies treat this as incidental and bundle it into the main subscription. However, this may represent a distinct performance obligation that should be separated and allocated its share of the transaction price in Metronome. ## Step 3: Determine the transaction price ### Accounting meaning The transaction price is the total amount the entity expects to be entitled to under the contract's enforceable term, and while it usually aligns with TCV (total contract value) it may differ depending on how TCV is defined. The transaction price can include: * Fixed fees (subscription fee, flat setup fee) * Variable usage fees (usage-based fees, overages) * Discounts and credits * Constraints on variable consideration to avoid overstatement ### Customer challenges * Capturing all pricing components separately for accounting purposes, such that the total contract value (transaction price) within Metronome is accurate * Handling variable consideration (VC), including tracking and mapping to usage. Metronome's system can accommodate variable components like overages and rollovers. For complex scenarios, Metronome clients may need to estimate the transaction price to effectively defer revenue * Understanding how much of billed amounts are fixed vs. variable, and how discounts or credits were applied * Maintaining a record of all adjustments ### How Metronome supports * **Granular price capture** provides separate fields for fixed, variable, discounts, credits * **Raw usage linkage** stores raw usage alongside the final billed amount for auditability * **Flexible contract and rate card architecture** supports varied commercial models and dynamic pricing structures for ramped deals and tiered pricing structures * **Adjustment tracking** with exported logs of discounts, credits, and reason codes * **Currency handling** supported by storing original and functional currency amounts **Key product focus:** Make sure all pricing elements are explicitly stored and exportable and not buried in aggregated totals. ### Mapping to Metronome's current documentation * **[How Metronome works - Price: Products & Rate Cards section](/guides/get-started/how-metronome-works#price%3A-products-%26-rate-cards%E2%80%8B):** This section describes Rate Cards as defining the default pricing for usage products, supporting scheduled price changes and different tiers. This relates to how prices are set and applied across commercial models. The system also supports commit-specific pricing, incentivizing higher commitments with discounts. * **[How revenue recognition works - Terminology section](/guides/reporting-insights/financial-reporting/revenue-recognition#terminology):** This source defines concepts like On-demand usage, Commits (prepaid and postpaid), and Overage, which all contribute to the transaction price. * **[Sync into Salesforce](/integrations/platform-integrations/sfdc-integration):** The `metronome__Commit__c` data object includes `Total_Amount__c`, representing the total dollar amount of the commit or credit, which is a key component of the transaction price. The `metronome__Invoice__c` object includes `Total__c`, representing the invoice total. ### Critical callouts / Common issues #### Variable consideration Overage fees, rollovers, and future credits create complexity. Customers sometimes assume invoice amounts equal transaction price, but under ASC 606, VC may be required to be estimated and it could also be constrained. Metronome allows for capture and tracking of different types of consideration if designated correctly by the user. **Example:** A cloud storage provider charges \$120k for a base annual subscription plus \$0.05 per GB over a 1 TB limit. By October, a customer has fully consumed the prepaid balance and is issued an invoice for overages. Under ASC 606, those overages may represent variable consideration that should be estimated and constrained at contract inception, instead of recognized when billed. If the company simply books the invoice amounts, revenue could be misstated. #### Foreign currency ASC 606 requires consistent policy on FX treatment. While Metronome captures billing currency, users will need to ensure that their FX treatment is consistent under U.S. GAAP based on their currency designation(s). **Example:** A U.S.-based SaaS vendor (company) bills a German customer €100k annually. Metronome tracks the billing in euros, but ASC 606 requires revenue to be reported consistently in the company's functional currency (e.g., USD). The company must establish and apply a clear FX translation policy (e.g., using the contract inception rate or monthly average rates). ## Step 4: Allocate the transaction price ### Accounting meaning Once the total transaction price is determined, it must be allocated to the individual performance obligations based on their standalone selling price (SSP; i.e., relative selling price). This step ensures that discounting of one product or SKU doesn't mismatch its value, and it can be challenging, especially with bundled services or complex discount structures. Allocation affects the amount of revenue recognized for each obligation. ### Customer challenges * Determining SSPs for performance obligations and properly allocating consideration in ERP/revenue tools * Retaining historical data for reallocation if SSPs change ### How Metronome supports * **Charge-level reporting** by SKU/obligation * **Usage-to-obligation mapping** for every event and charge * **Data formatted** so ERP systems can allocate automatically without manual intervention * **Historical allocation support** including the availability of historical data from which to determine/support SSP analysis, and the ability to retain raw amounts even after pricing changes in case a customer's SSP changes and allocations are needed for past periods * **Maintain consistent identifiers** across all reports and APIs for allocation mapping Metronome's strength lies in its ability to track revenue at a granular level and provide the granular data necessary for allocation, but it does not perform reallocations. **Key product focus:** Preserve obligation-level allocation data in a clean, consistent format for downstream processing. ### Mapping to Metronome's current documentation * **[How Metronome works - Contracts: Encode Your Commercial Model](/guides/get-started/how-metronome-works#contracts%3A-encode-your-commercial-model%E2%80%8B):** This section describes how Contracts allow for custom terms and overrides, such as percentage or per-unit discounts, to be applied to specific products or product tags. While Metronome itself doesn't perform SSP allocation, it captures the custom pricing and discount structures at the contract level. * **[How revenue recognition works - Revenue reporting categories](/guides/reporting-insights/financial-reporting/revenue-recognition#revenue-reporting-categories):** Metronome's ability to break down revenue by product within each category (e.g., on-demand, commit drawdown) provides the granularity needed to track performance and helps facilitate allocation outside the system. * **[Sync into Salesforce](/integrations/platform-integrations/sfdc-integration):** The `metronome__Invoice_Line_Item__c` data object contains `Quantity__c`, `Unit_Price__c`, `Product_Type__c`, and `Total__c`, providing the specific data points that, when combined, can be used by the customer for price allocation logic. The `metronome__InvoiceLineItemPricingDimensionAssoc__c` and `metronome__Pricing_Dimension__c` objects also offer metadata for granular pricing details. ### Critical callouts / Common issues #### SSP allocation Metronome provides granular invoice data, but does not allocate transaction price across performance obligations. Companies may fail to adjust for relative SSP (Standalone Selling Price) allocations when discounts are bundled, whether a significant discount is included on a particular SKU or a service is included for "free". **Example:** A SaaS vendor (company) sells a \$100k annual subscription bundled with \$20k of professional services, discounting the package to \$105k total. Under ASC 606, the \$105k must be allocated to each performance obligation based on relative SSP. If the company simply books the \$100k subscription and \$5k services from the invoice data in Metronome, revenue will be misallocated. #### Commit / usage attribution Companies must determine how prepaid commits or rollovers relate to performance obligations. Without explicit allocation, they risk misclassification. **Example:** A cloud provider (company) sells a \$240k annual commit that includes \$20k of monthly usage credits. The customer uses only \$15k in some months and \$25k in others, with rollovers applying. Without clear attribution rules, the company may misclassify revenue (e.g., treating overages as new revenue instead of part of the original commit). #### Discounts and material rights Commit-specific discounts, tiered pricing, or future discount rights (e.g., renewal discounts) may create additional customer rights that require revenue allocation. **Example:** A SaaS vendor (company) sells a one-year contract for \$120k but also gives the customer a right to renew the following year at a 50% discount. That renewal option may be considered a "material right" under ASC 606. Part of the \$120k paid today would be allocated to the renewal right, not just to the first year of service. ## Step 5: Recognize revenue ### Accounting meaning The final step is to recognize revenue when or as performance obligations are satisfied. This can occur either over time (e.g., access to a platform over a period) or at points in time (e.g. as usage occurs, or a specific service is delivered). Metronome, as a usage-based platform, generally aligns with point in time recognition as usage occurs. However, it also supports subscriptions and seats which are typically recognized over time. ### Customer challenges * Matching usage to the correct recognition period * Handling true-ups and overages tied to prior periods * Differentiating between billing and earned revenue ### How Metronome supports * **Timestamped usage events** can be exported back to Data Warehouse for reconciliation * **Billed vs. earned views** in exports to separate invoicing from recognition * **True-up alignments** link adjustments back to the original usage period * **Long-term retention** of usage and billing data for audit lookbacks **Key product focus:** Ensure granularity + historical linkage so clients can confidently build recognition schedules. ### Mapping to Metronome's current documentation * **[How Metronome works - Invoice Generation: Bringing It All Together section](/guides/get-started/how-metronome-works#invoice-generation%3A-bringing-it-all-together%E2%80%8B):** This section explains that Metronome processes usage data, applies pricing from the customer's contract, and generates invoices in real-time with usage, on-demand via API, or at billing cycle close. This reflects the timing of when usage is measured and therefore when revenue could be recognized. * **[How revenue recognition works](/guides/reporting-insights/financial-reporting/revenue-recognition):** This section explains how Metronome maintains detailed transaction history and ledgers to calculate deferred, accrued, and recognized revenue with daily granularity down to products and revenue categories. It details how revenue is recognized for on-demand usage (immediately upon invoice issuance), prepaid commit drawdown (as commits are drawn down or expire), and postpaid commits (as usage occurs or when true-up invoices are issued). * **[How revenue recognition works - Metronome data model](/guides/reporting-insights/financial-reporting/revenue-recognition#metronome-data-model):** This section explains that querying invoices with `status = 'FINALIZED'` produces a report of recognized revenue, while `status = 'DRAFT'` produces a report of accrued revenue. It also details specific ledger entry types for credits and commits that are relevant to revenue recognition, indicating when certain amounts should be recognized (e.g., `prepaid_segment_expiration` should always be recognized as revenue). * **[Revenue recognition examples](/guides/reporting-insights/financial-reporting/revenue-recognition-examples):** This source provides concrete scenarios (e.g., on-demand usage with free credits, prepaid commitments, postpaid commitments) with accompanying data export tables and explanations of how CloudNet (the example company) recognizes revenue in each situation. ### Critical callouts / Common issues #### Timing of revenue recognition Metronome shows usage in real time, but companies must confirm that their policy is point in time (as consumed) vs. over time (ratable) recognition. **Example:** A SaaS vendor (company) charges per API call. Metronome shows usage in real time, but under ASC 606, the company must decide whether the API service transfers at a point in time (each call) or over time (continuous access). If treated incorrectly, revenue may be accelerated or deferred improperly. #### Cutoff / partial month issues Daily breakdowns solve cutoff problems, but if companies don't use them, they may incorrectly prorate revenue at month-end. **Example:** A SaaS company's contract starts on March 20. If they only recognize revenue by full months instead of using Metronome's daily breakdown, they may record all of March's revenue even though the service was only provided for 12 days, overstating revenue for that period. #### Breakage estimates If you expect breakage, recognize it in proportion to the pattern of rights exercised, subject to the constraint. Companies often fail to estimate breakage upfront, leading to deferral errors. **Example:** The customer of a SaaS vendor (company) prepays \$120k for annual usage credits but historically only uses about 80%. Under ASC 606, the company may need to estimate and recognize expected breakage (\$24k) as revenue over the service period. If they wait until credits expire, they may understate revenue throughout the year and then have a large "catch-up" later. #### Invoicing vs. revenue recognition timing Recognize revenue when control transfers (per-event point in time or, for stand-ready arrangements, over time), not when invoices are issued. Invoice timing and recognition often differ. Companies may incorrectly align revenue only with invoice timing, missing accrued-but-unbilled obligations **Example:** A vendor invoices \$120k upfront for a one-year subscription. Under ASC 606, revenue must be recognized ratably as services are provided, not when invoiced. If the company books the full \$120k in January, they've overstated Q1 revenue and understated the remainder of the year. ## Appendix: Examples and data components Metronome provides the foundational data needed to support complex revenue recognition requirements in usage-based business models. Through detailed transaction history, ledger entries, and configurable pricing logic, Metronome enables its clients to calculate deferred, accrued, and recognized revenue with daily granularity. This data is accessible via Metronome's APIs or data export functionality and can be integrated into external revenue subledgers, ERPs, or custom reports exportable as CSVs. Metronome's data model includes: * Invoice timestamps (`invoices.start_timestamp`, `invoices.end_timestamp`) to define service periods * Line item attributes (`line_items.product_id`, `line_items.commit_id`) for product-level revenue recognition * Credit and balance ledger entries to support treatment of prepaid, postpaid, free credits, and expirations Below are common revenue scenarios and how Metronome's data components map to each use case: ### 1. On-demand (pay-as-you-go) usage **Description:** Customer is billed based on actual usage with no precommitments. **Revenue recognition:** Recognized at the time of invoicing, as usage is incurred. **Metronome data mapping:** * `invoices.type = 'CONTRACT_USAGE'` for usage-based billing * `line_items.commit_id = null` indicates on-demand or overage (differentiated via metadata) **Example:** Customer A incurs \$384 for CloudCompute and \$75 for CloudStorage between Jan 16–31, invoiced on at the end of the month and recognized as on-demand revenue. ### 2. Prepaid commitment drawdown **Description:** Customer prepays a fixed amount (e.g., \$10,000) for future usage at a discount. **Revenue recognition:** Prepayment deferred initially; recognized as revenue as credits are consumed. **Metronome data mapping:** * `invoices.type = 'CONTRACT_SCHEDULED'` for the initial prepaid commit (deferred revenue) * `invoices.type = 'CONTRACT_USAGE'` for usage during drawdown (often \$0 invoices) * `line_items.commit_id` populated; joins to `balances.type = 'prepaid'` **Example:** \$900 of usage is consumed against a \$10,000 commit and recognized upon consumption, even if no invoice is issued for usage. ### 3. Prepaid commit expirations (breakage) **Description:** Unused credits at the end of the commitment period are expired. **Revenue recognition:** Recognized as revenue when expired (or earlier if using a breakage model). **Metronome data mapping:** * `balances_ledger.entry_type = 'prepaid_segment_expiration'` indicates credit expiration * No invoice is issued; the expiration is tracked via the ledger **Example:** \$1,400 of unused commit is expired on Jan 1, 2025, and recognized as revenue as the company does not have a history of rolling over expired credits. ### 4. Postpaid commitment drawdown **Description:** Customer commits to a minimum spend but pays monthly in arrears. **Revenue recognition:** Recognized as usage occurs. **Metronome data mapping:** * `invoices.type = 'CONTRACT_SCHEDULED'` or `'CONTRACT_USAGE'` * `line_items.commit_id` populated; linked to `balances.type = 'postpaid'` **Example:** \$700 for CloudCompute and \$100 for CloudStorage is recognized for the month based on usage. ### 5. Postpaid commitment true-ups **Description:** Customer falls short of minimum commitment, and a true-up invoice is issued. **Revenue recognition:** Recognized when true-up invoice is finalized (unless rolled into a renewal). **Metronome data mapping:** * `invoices.type = 'CONTRACT_TRUEUP'` * `balances_ledger.entry_type = 'postpaid_trueup'` **Example:** A \$400 true-up is invoiced at the end of the term and recognized (upon expiration). ### 6. Overage usage **Description:** Usage exceeds the committed amount. **Revenue recognition:** Recognized upon invoicing. **Metronome data mapping:** * `line_items.commit_id = null` indicates overage (if no commit applies) * Differentiated from on-demand using client-defined metadata **Example:** \$900 of overage in month 11 is invoiced and recognized. ### 7. Free credits **Description:** Credits provided as promotions, free trials, or SLA compensation. **Revenue recognition:** Not deferred or recognized as revenue. May offset recognized revenue as contra-revenue. **Metronome data mapping:** * `balances_ledger.entry_type = 'credit_automated_invoice_deduction'` **Example:** \$410 in credits are applied to usage; \$90 of unused credits expire. ## Metronome data model highlights Metronome's data structure supports compliance with ASC 606 through the following capabilities: ### Product-level granularity Metronome categorizes revenue by type (on-demand, commit drawdown, overage) and product, enabling precision in revenue tracking and reporting. It does so while capturing detailed transaction history and ledgers with daily granularity, down to products and revenue categories, which is crucial for period-specific revenue recognition and audit support. ### Custom fields on SKUs Metronome clients can define performance obligations at the SKU level using custom fields, which are available in data exports for revenue allocation and categorization. ### Invoice line item detail * `line_items.commit_id`: indicates commit-based usage * `line_items.product_id`: used for product-level recognition * `invoices.credit_type_id`: identifies the billing currency * `invoices.start_timestamp` / `end_timestamp`: define the service delivery period ### Reporting and reconciliation Metronome provides invoicing information that is critical for determining deferred revenue balances and contract assets/liabilities. This data can be reconciled against external systems like Salesforce and Stripe. Metronome offers robust data exports and APIs that allow customers to extract detailed data (contracts, invoices, usage, pricing) for reconciliation with their external ERP or accounting systems. * `invoices.status = 'FINALIZED'`: used for recognized revenue * `invoices.status = 'DRAFT'`: used for revenue accruals These views support reconciliation of revenue recognized, deferred, and contract assets. ### Support for complex pricing Rate cards define default pricing, and can accommodate tiered pricing, composite charges, commit-specific pricing, scheduled price changes, and dynamic overrides. While the platform does not perform allocation under ASC 606, the necessary data for determining standalone selling prices is available. ### Contract management Metronome's contract object serves as a central hub for defining a customer's commercial model, including base pricing, custom terms, product access, payment structure (commitments, credits, subscriptions), and billing cycles, important for capturing TCV. Framework includes support for: * Multi-year ramp deals * Opt-out and renewal clauses * Access schedules for commitments * Parent-child account structures a.k.a. account hierarchy # How revenue recognition works Source: https://docs.metronome.com/guides/reporting-insights/financial-reporting/revenue-recognition Metronome powers usage-based business models by enabling pricing and packaging flexibility that support a broad range of business models and power a uniquely differentiated billing experience. As a result, Metronome stores all of the raw data necessary to manage complex revenue recognition for usage-based business models. This includes maintaining detailed transaction history and ledgers to calculate deferred revenue, accrued revenue, and recognized revenue, all with daily granularity down to products and revenue categories. This data is available either through Metronome's APIs or Metronome [data export](/guides/reporting-insights/data-export). Clients commonly use this data to: * Integrate the data directly to a downstream system using Metronome APIs to automate revenue recognition * Run data exports to create journal entries for posting to their enterprise resource planning (ERP) system **INFO** Metronome does not create revenue journal entries. ## Terminology This section defines key terms and how they apply to Metronome's support of your usage-based business. ### Revenue reporting categories Merchants frequently report recognized revenue in separate categories. The most common categories are: * On-demand (pay-as-you-go) usage * Prepaid commitment draw down * Postpaid commitment draw down * Overage usage * Credit draw down Within each category, revenue gets further broken down by product. This level of granularity allows merchants to track the performance of each go-to-market strategy, sales channel, and product offering. ### On-demand usage On-demand usage refers to a pricing model where customers are charged based on their actual consumption, without any preset spending commitments. Metronome issues invoices for on-demand consumption as it occurs. The merchant is entitled to recognize revenue immediately upon issuance of invoices for on-demand consumption. ### Commits A commit refers to a customer's agreement or promise to consume a certain amount of a product or service over a specified period. This concept is common in enterprise sales for AI, cloud computing, and software-as-a-service (SaaS) industries. Metronome supports two types of commits: prepaid and postpaid. #### Prepaid commits A prepaid commit refers to a customer's agreement to purchase commits (called prepaid credits) by making upfront payments. In exchange for the commitment, the customer may receive preferential terms, such as discounted draw down rates. Here's how revenue is allocated based on mechanics in Metronome: * **Invoice for purchases**: Metronome issues invoices to the customer to collect payment for each purchase of a prepaid commit. The merchant is entitled to defer revenue associated to purchases of prepaid commits. * **Draw down invoices**: Metronome issues invoices to draw down prepaid commit balances based on the customer's actual consumption each month during the commitment period. The merchant is entitled to recognize revenue as prepaid commits are drawn down. * **Expiration handling**: Metronome expires any unused prepaid commits at the end of each commitment period (commit expirations are also referred to as "prepaid commit true-ups"). The merchant is entitled to recognize revenue when a prepaid commit has expired. #### Postpaid commits A postpaid commit refers to a customer's agreement to spend a minimum amount over a preset period of time. In exchange for the commitment, the customer may receive preferential terms, such as discounted draw down rates. If the customer has not met the minimum spend amount by the end of the commitment period, a true-up invoice is issued for the difference between actual spending and the commitment amount. * **Draw down process**: Metronome draws down the postpaid commit balance based on the customer's actual consumption each month during the commitment period. The merchant is entitled to recognize this usage as revenue as postpaid commits are drawn down. * **True-up invoicing**: Metronome issues a true-up invoice to the customer at the end of the commitment period, if needed. The merchant is entitled to recognize revenue when true-up invoices are issued. For more information on how to set up commits in Metronome, navigate to [Apply credits and commits](/guides/pricing-packaging/apply-credits-and-commits/create-a-pre-paid-commit). ### Overage Overage refers to a customer's actual consumption spending that exceeds a preset commitment amount. Metronome issues invoices for overages as soon as they occur. The merchant is entitled to recognize this overage as revenue when invoices are issued. ### Issue free credits In Metronome, credits refer to free credits that are issued for free trials, promotions, SLA violations, concession credits, and similar use cases. These credits are always free and never paid for, whereas prepaid commits (sometimes referred to as "prepaid credits") are always paid for. Since credits are always free, they do not affect deferred revenue, but credit draw down may have a contra-revenue impact against recognized revenue. ### Billing in arrears versus billing in advance All Metronome usage charges are billed in arrears, with monthly, quarterly, and annual as possible billing options. Since these charges are billed in arrears, they can be recognized as revenue immediately upon invoicing, and can be accrued as needed. Metronome uses scheduled charges to issue invoices for prepaid commit purchases. Scheduled charges are billed in advance and are generally treated as deferred revenue upon invoicing. ### Accrued revenue Accrued revenue refers to revenue that has been earned, but invoices have not yet been issued, or payment has not yet been received. Accrued revenue may also be called "earned but un-billed" revenue. In Metronome, accrued revenue is represented by draft usage invoices, which are an accumulation of usage events that have been rated, but not yet invoiced. ## Metronome data model To create the necessary queries for revenue recognition, it is important to first understand the Metronome data model. The ERD below shows a simplified view of the Metronome objects in data export that contain the relevant information for revenue recognition. Metronome revenue recognition data model ### Key data model relationships 1. Each credit has a credit ledger. The credit ledger entry types relevant to revenue recognition are: * `credit_automated_invoice_deduction` represents a reduction of the credit balance from an invoice * If reporting on revenue from `line_items`, ignore this ledger entry type as revenue is already included from `line_items` where `invoices.type` = `CONTRACT_USAGE` * `credit_segment_expiration` represents the expiration of the credit balance segment (aka true-up) * This ledger entry is usually ignored as credit expirations do not impact revenue 2. Each commit has a commit ledger. The commit ledger entry types relevant to revenue recognition are: * `prepaid_automated_invoice_deduction` represents a reduction of the prepaid commit balance from an invoice * If reporting on revenue from `line_items`, ignore this ledger entry type as revenue is already included from `line_items` where `invoices.type` = `CONTRACT_USAGE` * `prepaid_segment_expiration` represents the expiration of the prepaid commit balance segment * Always recognize revenue from this ledger entry as prepaid expirations are not invoiced by Metronome * `postpaid_automated_invoice_deduction` represents a reduction of the postpaid commit balance from an invoice * If reporting on revenue from `line_items`, ignore this ledger entry type as revenue is already included from `line_items` where `invoices.type` = `CONTRACT_TRUEUP` * `postpaid_trueup` represents a true-up invoice that was issued for this postpaid commit to invoice for the remainder of the postpaid commit balance * If reporting on revenue from `line_items`, ignore this ledger entry type as amounts are duplicated 3. In data export, `credits` and `commits` objects are consolidated into the `balances` object to simplify reporting. 4. Metronome creates different invoice types based on the type of charges that are invoiced: * When `invoices.type = 'CONTRACT_SCHEDULED'`, the invoice contains scheduled charges, including prepaid commit purchases * When `invoices.type = 'CONTRACT_USAGE'`, the invoice contains usage charges * When `invoices.type = 'CONTRACT_TRUEUP'`, the invoice contains true-up charges for postpaid commits 5. Each invoice has one or more line items, which indicate the amount of revenue to recognize: * `invoices.credit_type_id` indicates the billing currency (for example, USD cents) * `invoices.start_timestamp` and `invoices.end_timestamp` indicate the service period * The Metronome service period determines the target accounting period in the ERP system * `line_items.product_id` indicates which product is being invoiced * `line_items.product_id` is mapped to a SKU or line item ID in the ERP system * If `line_items.commit_id` is populated, a credit or commit has been applied to the line item * Join `line_items` to `balances` (`line_items.commit_id = balances.id`) to fetch `balances.type` * `balances.type` determines whether line item amount should be categorized as credit, prepaid commit, or postpaid commit revenue * The enumerations for `balances.type` are: `credit`, `prepaid`, or `postpaid` * If `line_items.commit_id` is null, this indicates the line item amount should be categorized as either on-demand (pay-as-you-go) or overage revenue * Use metadata (client defined) on the `contracts` or `commits` objects to differentiate on-demand (pay-as-you-go) versus overage revenue 6. Querying invoices where `status = 'FINALIZED'` will produce a report of recognized revenue 7. Querying invoices where `status = 'DRAFT'` will produce a report of accrued revenue **INFO** Data export will transfer two distinct invoice tables - one for finalized and one for draft invoices. # Revenue recognition examples Source: https://docs.metronome.com/guides/reporting-insights/financial-reporting/revenue-recognition-examples This page demonstrates how an example company called CloudNet handles revenue recognition with Metronome. CloudNet offers two products: * CloudCompute, billed at \$1/CPU hour * CloudStorage, billed at \$0.50/GB storage monthly ## Data export tables​ For each scenario below, Metronome populates data export tables in CloudNet’s object storage destination or data warehouse. In turn, CloudNet can use this data, based on the rules described in the parent section, to accurately recognize revenue for its usage based business. | Table name | Description | | ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Customer | This table contains customer metadata like CRM customer ID or ERP customer ID that are needed to match Metronome’s billing data to downstream systems for revenue recognition. | | Contract | This table contains metadata like contract type, opportunity ID, or sales order ID that are needed to match Metronome’s billing data to downstream systems for revenue recognition. | | Invoice | This table contains all invoices generated by Metronome. Invoices include `invoices.type` , which indicates the types of charges included on each invoice (prepaid commit purchase, usage, or postpaid commit true-up). | | Invoice line items | This table contains all line items associated to each invoice. Line items include:
  • `commit_id`, necessary for determination of revenue category (credit drawdown, on demand, prepaid commit drawdown, postpaid commit drawdown, or overage)
  • `product_id`, necessary for recognizing revenue against specific products
  • `starting_at` and `ending_before`, necessary for determining the revenue recognition service period
| | Balances | This table contains a consolidation of all credits and commits. Balances include `balances.type` , which indicates if the balance is prepaid, postpaid, or credit. Each balance contains a ledger, which tracks all invoice deductions, manual adjustments, expirations, or true-ups. | ## Scenario 1: On-demand (pay-as-you-go) usage with free credits​ In this scenario, Customer A signs up for a free trial to CloudNet on Jan 1, and receives \$500 worth of free credits that expire in 15 days. From Jan 1 to Jan 15, Customer A consumes 360 hours of CloudCompute and 100 GB of CloudStorage. From Jan 15 to Jan 31, Customer A consumes 384 hours of CloudCompute and 150 GB of CloudStorage. As a result of that scenario, the data shown in these tables populates in the CloudNet warehouse through Metronome data export. **Customer** | id | name | | ----- | ---------- | | 10001 | Customer A | **Contract** | id | customer\_id | starting\_at | ending\_before | | ----- | ------------ | ----------------- | -------------- | | 20001 | 10001 | Jan 1, 2024 00:00 | null | **Invoice** | id | invoice\_type | total | issued\_at | start\_timestamp | end\_timestamp | contract\_id | | ----- | --------------- | ----- | ----------- | ----------------- | ----------------- | ------------ | | 30001 | CONTRACT\_USAGE | 459 | Feb 1, 2024 | Jan 1, 2024 00:00 | Feb 1, 2024 00:00 | 20001 | **Invoice line items** | id | invoice\_id | quantity | unit\_price | total | line\_item\_name | product\_name | commit\_id | starting\_at | ending\_before | | ----- | ----------- | -------- | ----------- | ----- | ---------------------------- | ------------- | ---------- | ------------------ | ------------------ | | 40001 | 30001 | 360 | 1.00 | 360 | CloudCompute | CloudCompute | 50001 | Jan 1, 2024 00:00 | Jan 16, 2024 00:00 | | 40002 | 30001 | 100 | 0.50 | 50 | CloudStorage | CloudStorage | 50001 | Jan 1, 2024 00:00 | Jan 16, 2024 00:00 | | 40003 | 30001 | 1 | null | -360 | Free\_trial\_credits applied | CloudCompute | 50001 | Jan 1, 2024 00:00 | Jan 16, 2024 00:00 | | 40004 | 30001 | 1 | null | -50 | Free\_trial\_credits applied | CloudStorage | 50001 | Jan 1, 2024 00:00 | Jan 16, 2024 00:00 | | 40005 | 30001 | 384 | 1.00 | 384 | CloudCompute | CloudCompute | null | Jan 16, 2024 00:00 | Feb 1, 2024 00:00 | | 40006 | 30001 | 150 | 0.50 | 75 | CloudStorage | CloudStorage | null | Jan 16, 2024 00:00 | Feb 1, 2024 00:00 | **Balances ledger** | balances\_id | customer\_id | contract id | name | ledger type | ledger\_entry\_id | ledger entry type | ledger entry timestamp | ledger entry amount | | ------------ | ------------ | ----------- | -------------------- | ----------- | ----------------- | ------------------------------------- | ---------------------- | ------------------- | | 50001 | 10001 | 20001 | Free\_trial\_credits | CREDIT | 60001 | credit\_segment\_start | Jan 1, 2024 00:00 | 500 | | 50001 | 10001 | 20001 | Free\_trial\_credits | CREDIT | 60002 | credit\_automated\_invoice\_deduction | Jan 16, 2024 00:00 | -410 | | 50001 | 10001 | 20001 | Free\_trial\_credits | CREDIT | 60003 | credit\_segment\_expiration | Jan 16, 2024 00:00 | -90 | Using the table data, CloudNet recognizes this revenue: On Feb 1, Metronome issues a usage invoice for \$459. * The merchant can report that \$360 of free credits were applied to CloudCompute * The merchant can report that \$50 of free credits were applied to CloudStorage * The merchant can report that \$90 of free credits were expired * The merchant can recognize \$384 of on-demand revenue for CloudCompute * The merchant can recognize \$150 of on-demand revenue for CloudStorage ## Scenario 2a: Prepaid commitment (upfront payment and first month of usage)​ In this scenario, Customer B agrees to a prepaid commitment of \$10,000 on Jan 1, 2024. The prepayment is due immediately and the commitment period is 1 year. In return for the prepaid commitment, Customer B receives a 20% discount off of list rates. From Jan 1 to Jan 31, Customer B consumes 1000 hours of CloudCompute and 250 GB of CloudStorage. As a result of that scenario, the data shown in these tables populates in the CloudNet warehouse through Metronome data export. **Customer** | id | name | | ----- | ---------- | | 10002 | Customer B | **Contract** | id | customer\_id | starting\_at | ending\_before | | ----- | ------------ | ----------------- | -------------- | | 20002 | 10001 | Jan 1, 2024 00:00 | Jan 1, 2025 | **Invoice** | id | invoice\_type | total | issued\_at | start\_timestamp | end\_timestamp | contract\_id | | ----- | ------------------- | ------ | ----------- | ----------------- | ----------------- | ------------ | | 30002 | CONTRACT\_SCHEDULED | 10,000 | Jan 1, 2024 | Jan 1, 2024 00:00 | Feb 1, 2024 00:00 | 20002 | | 30003 | CONTRACT\_USAGE | 0 | Feb 1, 2024 | Jan 1, 2024 00:00 | Feb 1, 2024 00:00 | 20002 | **Invoice line items** | id | invoice\_id | quantity | unit\_price | total | line\_item\_name | product\_name | commit\_id | starting\_at | ending\_before | | ----- | ----------- | -------- | ----------- | ----- | --------------------------- | -------------- | ---------- | ----------------- | ----------------- | | 40005 | 30002 | 1 | 10000 | 10000 | Prepaid Commit | Prepaid Commit | 50002 | Jan 1, 2024 00:00 | Jan 1, 2024 00:00 | | 40006 | 30003 | 1,000 | 0.80 | 800 | CloudCompute | CloudCompute | 50002 | Jan 1, 2024 00:00 | Feb 1, 2024 00:00 | | 40007 | 30003 | 250 | 0.40 | 100 | CloudStorage | CloudStorage | 50002 | Jan 1, 2024 00:00 | Feb 1, 2024 00:00 | | 40008 | 30003 | 1 | null | -800 | prepaid\_commitment applied | CloudCompute | 50002 | Jan 1, 2024 00:00 | Feb 1, 2024 00:00 | | 40009 | 30003 | 1 | null | -100 | prepaid\_commitment applied | CloudStorage | 50002 | Jan 1, 2024 00:00 | Feb 1, 2024 00:00 | **Balances ledger** | balances\_id | customer\_id | contract id | name | ledger type | ledger entry type | ledger entry timestamp | ledger entry amount | | ------------ | ------------ | ----------- | ------------------- | ----------- | -------------------------------------- | ---------------------- | ------------------- | | 50002 | 10002 | 20002 | prepaid\_commitment | PREPAID | prepaid\_segment\_start | Jan 1, 2024 00:00 | 10,000 | | 50002 | 10002 | 20002 | prepaid\_commitment | PREPAID | prepaid\_automated\_invoice\_deduction | Feb 1, 2024 00:00 | -900 | Using the table data, CloudNet recognizes this revenue: On Jan 1, Metronome issues a scheduled invoice for \$10,000. * The merchant can defer \$10,000 of prepaid commit revenue On Feb 1, Metronome issues a usage invoice for \$0. * The merchant can recognize \$800 of prepaid commit revenue for CloudCompute * The merchant can recognize \$100 of prepaid commit revenue for CloudStorage ## Scenario 2b: Prepaid commitment (commit burn down and true-up)​ In this scenario, Customer B continues to burn down \$700 of prepaid commits every month during their contract (\$600 for CloudCompute and \$100 for CloudStorage). Metronome issues a zero-dollar invoice each month while the commit balance is drawn down. At the end of month 12, Metronome expires the remaining commit balance (\$1,400). As a result of that scenario, the data shown in these tables populates in the CloudNet warehouse through Metronome data export. | **Month** | **Usage Charges** | **Overage Charges** | **Invoice Total** | **Remaining Commit Balance** | | --------- | ----------------- | ------------------- | ----------------- | ---------------------------- | | 1 | 900 | 0 | 0 | 9,100 | | 2 | 700 | 0 | 0 | 8,400 | | 3 | 700 | 0 | 0 | 7,700 | | 4 | 700 | 0 | 0 | 7,000 | | 5 | 700 | 0 | 0 | 6,300 | | 6 | 700 | 0 | 0 | 5,600 | | 7 | 700 | 0 | 0 | 4,900 | | 8 | 700 | 0 | 0 | 4,200 | | 9 | 700 | 0 | 0 | 3,500 | | 10 | 700 | 0 | 0 | 2,800 | | 11 | 700 | 0 | 0 | 2,100 | | 12 | 700 | 0 | 0 | 1,400 | **Invoice** | id | invoice\_type | total | issued\_at | start\_timestamp | end\_timestamp | contract\_id | | ----- | ------------------- | ------ | ----------- | ----------------- | ----------------- | ------------ | | 30002 | CONTRACT\_SCHEDULED | 10,000 | Jan 1, 2024 | Jan 1, 2024 00:00 | Feb 1, 2024 00:00 | 20002 | | 30003 | CONTRACT\_USAGE | 0 | Feb 1, 2024 | Jan 1, 2024 00:00 | Feb 1, 2024 00:00 | 20002 | | 30004 | CONTRACT\_USAGE | 0 | Mar 1, 2024 | Feb 1, 2024 00:00 | Mar 1, 2024 00:00 | 20002 | | 30005 | CONTRACT\_USAGE | 0 | Apr 1, 2024 | Mar 1, 2024 00:00 | Apr 1, 2024 00:00 | 20002 | | 30006 | CONTRACT\_USAGE | 0 | May 1, 2024 | Apr 1, 2024 00:00 | May 1, 2024 00:00 | 20002 | | 30007 | CONTRACT\_USAGE | 0 | Jun 1, 2024 | May 1, 2024 00:00 | Jun 1, 2024 00:00 | 20002 | | 30008 | CONTRACT\_USAGE | 0 | Jul 1, 2024 | Jun 1, 2024 00:00 | Jul 1, 2024 00:00 | 20002 | | 30009 | CONTRACT\_USAGE | 0 | Aug 1, 2024 | Jul 1, 2024 00:00 | Aug 1, 2024 00:00 | 20002 | | 30010 | CONTRACT\_USAGE | 0 | Sep 1, 2024 | Aug 1, 2024 00:00 | Sep 1, 2024 00:00 | 20002 | | 30011 | CONTRACT\_USAGE | 0 | Oct 1, 2024 | Sep 1, 2024 00:00 | Oct 1, 2024 00:00 | 20002 | | 30012 | CONTRACT\_USAGE | 0 | Nov 1, 2024 | Oct 1, 2024 00:00 | Nov 1, 2024 00:00 | 20002 | | 30013 | CONTRACT\_USAGE | 0 | Dec 1, 2024 | Nov 1, 2024 00:00 | Dec 1, 2024 00:00 | 20002 | | 30014 | CONTRACT\_USAGE | 0 | Jan 1, 2025 | Dec 1, 2024 00:00 | Jan 1, 2025 00:00 | 20002 | **Balances ledger** | balances\_id | customer\_id | contract id | name | ledger\_type | ledger\_entry\_id | ledger\_entry\_type | ledger\_entry\_timestamp | ledger\_entry\_amount | | ------------ | ------------ | ----------- | ------------------- | ------------ | ----------------- | -------------------------------------- | ------------------------ | --------------------- | | 50002 | 10002 | 20002 | prepaid\_commitment | PREPAID | 60001 | prepaid\_segment\_start | Jan 1, 2024 00:00 | 10,000 | | 50002 | 10002 | 20002 | prepaid\_commitment | PREPAID | 60002 | prepaid\_automated\_invoice\_deduction | Feb 1, 2024 00:00 | -900 | | 50002 | 10002 | 20002 | prepaid\_commitment | PREPAID | 60003 | prepaid\_automated\_invoice\_deduction | Mar 1, 2024 00:00 | -700 | | 50002 | 10002 | 20002 | prepaid\_commitment | PREPAID | 60004 | prepaid\_automated\_invoice\_deduction | Apr 1, 2024 00:00 | -700 | | 50002 | 10002 | 20002 | prepaid\_commitment | PREPAID | 60005 | prepaid\_automated\_invoice\_deduction | May 1, 2024 00:00 | -700 | | 50002 | 10002 | 20002 | prepaid\_commitment | PREPAID | 60006 | prepaid\_automated\_invoice\_deduction | Jun 1, 2024 00:00 | -700 | | 50002 | 10002 | 20002 | prepaid\_commitment | PREPAID | 60007 | prepaid\_automated\_invoice\_deduction | Jul 1, 2024 00:00 | -700 | | 50002 | 10002 | 20002 | prepaid\_commitment | PREPAID | 60008 | prepaid\_automated\_invoice\_deduction | Aug 1, 2024 00:00 | -700 | | 50002 | 10002 | 20002 | prepaid\_commitment | PREPAID | 60009 | prepaid\_automated\_invoice\_deduction | Sep 1, 2024 00:00 | -700 | | 50002 | 10002 | 20002 | prepaid\_commitment | PREPAID | 60010 | prepaid\_automated\_invoice\_deduction | Oct 1, 2024 00:00 | -700 | | 50002 | 10002 | 20002 | prepaid\_commitment | PREPAID | 60011 | prepaid\_automated\_invoice\_deduction | Nov 1, 2024 00:00 | -700 | | 50002 | 10002 | 20002 | prepaid\_commitment | PREPAID | 60012 | prepaid\_automated\_invoice\_deduction | Dec 1, 2024 00:00 | -700 | | 50002 | 10002 | 20002 | prepaid\_commitment | PREPAID | 60013 | prepaid\_automated\_invoice\_deduction | Jan 1, 2025 00:00 | -700 | | 50002 | 10002 | 20002 | prepaid\_commitment | PREPAID | 60014 | prepaid\_segment\_expiration | Jan 1, 2025 00:00 | -1,400 | Using the table data, CloudNet recognizes the following revenue: * In month 1, Metronome issues a \$0 usage invoice * The merchant can recognize \$800 of prepaid commit revenue for CloudCompute * The merchant can recognize \$100 of prepaid commit revenue for CloudStorage * From months 2 - 12, Metronome issues a \$0 usage invoices * The merchant can recognize \$700 of prepaid commit revenue for CloudCompute each month * The merchant can recognize \$100 of prepaid commit revenue for CloudStorage each month * On Jan 1, 2025, Metronome expires \$1400 remaining balance of unused prepaid commit * The merchant can recognize \$1400 of prepaid commit revenue ## Scenario 2c: Prepaid commitment (commit burn down and overage)​ In this scenario, Customer B continues to burn down \$1,000 (\$900 for CloudCompute and \$100 for CloudStorage) of prepaid commits every month during their contract. Metronome issues a zero-dollar invoice each month while the commit balance is drawn down. Starting in month 11, Customer B starts to incur overage charges. As a result of that scenario, the data shown in these tables populates in the CloudNet warehouse through Metronome data export. | **Month** | **Usage Charges** | **Overage Charges** | **Invoice Total** | **Remaining Commit Balance** | | --------- | ----------------- | ------------------- | ----------------- | ---------------------------- | | 1 | 900 | 0 | 0 | 9,100 | | 2 | 1,000 | 0 | 0 | 8,100 | | 3 | 1,000 | 0 | 0 | 7,100 | | 4 | 1,000 | 0 | 0 | 6,100 | | 5 | 1,000 | 0 | 0 | 5,100 | | 6 | 1,000 | 0 | 0 | 4,100 | | 7 | 1,000 | 0 | 0 | 3,100 | | 8 | 1,000 | 0 | 0 | 2,100 | | 9 | 1,000 | 0 | 0 | 1,100 | | 10 | 1,000 | 0 | 0 | 100 | | 11 | 1,000 | 900 | 800 | 0 | | 12 | 1,000 | 1,000 | 1,000 | 0 | **Invoice** | id | invoice\_type | total | issued\_at | start\_timestamp | end\_timestamp | contract\_id | | ----- | ------------------- | ------ | ----------- | ----------------- | ----------------- | ------------ | | 30002 | CONTRACT\_SCHEDULED | 10,000 | Jan 1, 2024 | Jan 1, 2024 00:00 | Feb 1, 2024 00:00 | 20002 | | 30003 | CONTRACT\_USAGE | 0 | Feb 1, 2024 | Jan 1, 2024 00:00 | Feb 1, 2024 00:00 | 20002 | | 30004 | CONTRACT\_USAGE | 0 | Mar 1, 2024 | Feb 1, 2024 00:00 | Mar 1, 2024 00:00 | 20002 | | 30005 | CONTRACT\_USAGE | 0 | Apr 1, 2024 | Mar 1, 2024 00:00 | Apr 1, 2024 00:00 | 20002 | | 30006 | CONTRACT\_USAGE | 0 | May 1, 2024 | Apr 1, 2024 00:00 | May 1, 2024 00:00 | 20002 | | 30007 | CONTRACT\_USAGE | 0 | Jun 1, 2024 | May 1, 2024 00:00 | Jun 1, 2024 00:00 | 20002 | | 30008 | CONTRACT\_USAGE | 0 | Jul 1, 2024 | Jun 1, 2024 00:00 | Jul 1, 2024 00:00 | 20002 | | 30009 | CONTRACT\_USAGE | 0 | Aug 1, 2024 | Jul 1, 2024 00:00 | Aug 1, 2024 00:00 | 20002 | | 30010 | CONTRACT\_USAGE | 0 | Sep 1, 2024 | Aug 1, 2024 00:00 | Sep 1, 2024 00:00 | 20002 | | 30011 | CONTRACT\_USAGE | 0 | Oct 1, 2024 | Sep 1, 2024 00:00 | Oct 1, 2024 00:00 | 20002 | | 30012 | CONTRACT\_USAGE | 0 | Nov 1, 2024 | Oct 1, 2024 00:00 | Nov 1, 2024 00:00 | 20002 | | 30013 | CONTRACT\_USAGE | 900 | Dec 1, 2024 | Nov 1, 2024 00:00 | Dec 1, 2024 00:00 | 20002 | | 30014 | CONTRACT\_USAGE | 1,000 | Jan 1, 2025 | Dec 1, 2024 00:00 | Jan 1, 2025 00:00 | 20002 | **Invoice line item (overage invoice only)** | id | invoice id | quantity | unit\_price | total | line\_item\_name | product\_name | commit id | starting\_at | ending\_before | | ----- | ---------- | -------- | ----------- | ----- | --------------------------- | ------------- | --------- | ----------------- | ----------------- | | 40006 | 30013 | 1,000 | 0.80 | 800 | CloudCompute | CloudCompute | 50002 | Nov 1, 2024 00:00 | Dec 1, 2024 00:00 | | 40007 | 30013 | 500 | 0.40 | 200 | CloudStorage | CloudStorage | 50002 | Nov 1, 2024 00:00 | Dec 1, 2024 00:00 | | 40008 | 30013 | 1 | null | -100 | prepaid\_commitment applied | CloudCompute | 50002 | Nov 1, 2024 00:00 | Dec 1, 2024 00:00 | **Balances ledger** | balances\_id | customer\_id | contract id | name | ledger\_type | ledger\_entry\_id | ledger\_entry\_type | ledger\_entry\_timestamp | ledger\_entry\_amount | | ------------ | ------------ | ----------- | ------------------- | ------------ | ----------------- | -------------------------------------- | ------------------------ | --------------------- | | 50002 | 10002 | 20002 | prepaid\_commitment | PREPAID | 60001 | prepaid\_segment\_start | Jan 1, 2024 00:00 | 10,000 | | 50002 | 10002 | 20002 | prepaid\_commitment | PREPAID | 60002 | prepaid\_automated\_invoice\_deduction | Feb 1, 2024 00:00 | -900 | | 50002 | 10002 | 20002 | prepaid\_commitment | PREPAID | 60003 | prepaid\_automated\_invoice\_deduction | Mar 1, 2024 00:00 | -1,000 | | 50002 | 10002 | 20002 | prepaid\_commitment | PREPAID | 60004 | prepaid\_automated\_invoice\_deduction | Apr 1, 2024 00:00 | -1,000 | | 50002 | 10002 | 20002 | prepaid\_commitment | PREPAID | 60005 | prepaid\_automated\_invoice\_deduction | May 1, 2024 00:00 | -1,000 | | 50002 | 10002 | 20002 | prepaid\_commitment | PREPAID | 60006 | prepaid\_automated\_invoice\_deduction | Jun 1, 2024 00:00 | -1,000 | | 50002 | 10002 | 20002 | prepaid\_commitment | PREPAID | 60007 | prepaid\_automated\_invoice\_deduction | Jul 1, 2024 00:00 | -1,000 | | 50002 | 10002 | 20002 | prepaid\_commitment | PREPAID | 60008 | prepaid\_automated\_invoice\_deduction | Aug 1, 2024 00:00 | -1,000 | | 50002 | 10002 | 20002 | prepaid\_commitment | PREPAID | 60009 | prepaid\_automated\_invoice\_deduction | Sep 1, 2024 00:00 | -1,000 | | 50002 | 10002 | 20002 | prepaid\_commitment | PREPAID | 60010 | prepaid\_automated\_invoice\_deduction | Oct 1, 2024 00:00 | -1,000 | | 50002 | 10002 | 20002 | prepaid\_commitment | PREPAID | 60011 | prepaid\_automated\_invoice\_deduction | Nov 1, 2024 00:00 | -1,000 | | 50002 | 10002 | 20002 | prepaid\_commitment | PREPAID | 60012 | prepaid\_automated\_invoice\_deduction | Dec 1, 2024 00:00 | -1,000 | | 50002 | 10002 | 20002 | prepaid\_commitment | PREPAID | 60013 | prepaid\_automated\_invoice\_deduction | Jan 1, 2025 00:00 | -1,000 | Using the table data, CloudNet recognizes the following revenue: * In month 1, Metronome issues a \$0 usage invoice * The merchant can recognize \$800 of prepaid commit revenue for CloudCompute * The merchant can recognize \$100 of prepaid commit revenue for CloudStorage * From months 2 - 10, Metronome a issues \$0 usage invoices * The merchant can recognize \$900 of prepaid commit revenue for CloudCompute each month * The merchant can recognize \$100 of prepaid commit revenue for CloudStorage each month * In month 11, Metronome issues a \$900 usage invoice * The merchant can recognize \$900 of prepaid commit revenue for CloudCompute * The merchant can recognize \$100 of prepaid commit revenue for CloudStorage * In month 12, Metronome issues a \$1000 usage invoice * The merchant can recognize \$900 of prepaid commit revenue for CloudCompute * The merchant can recognize \$100 of prepaid commit revenue for CloudStorage ## Scenario 3: Postpaid commitment, with true-up invoice​ In this scenario, Customer C agrees to a postpaid commitment of \$10,000. They consume \$800 (\$700 of CloudCompute, \$100 of CloudStorage) of usage each month for 12 months. At the end of the commitment period, their cumulative spending is \$9,600. Metronome issues a true-up invoice of \$400 to true-up the remaining commitment balance. As a result of that scenario, the data shown in these tables populates in the CloudNet warehouse through Metronome data export. Customer | id | name | | ----- | ---------- | | 10003 | Customer C | Contract | id | customer\_id | starting\_at | ending\_before | | ----- | ------------ | ----------------- | -------------- | | 20003 | 10003 | Jan 1, 2024 00:00 | Jan 1, 2025 | Invoice | id | invoice\_type | total | issued\_at | start\_timestamp | end\_timestamp | contract\_id | | ----- | ------------------- | ----- | ----------- | ----------------- | ----------------- | ------------ | | 30002 | CONTRACT\_SCHEDULED | 800 | Feb 1, 2024 | Jan 1, 2024 00:00 | Feb 1, 2024 00:00 | 20003 | | 30003 | CONTRACT\_SCHEDULED | 800 | Mar 1, 2024 | Feb 1, 2024 00:00 | Mar 1, 2024 00:00 | 20003 | | 30004 | CONTRACT\_SCHEDULED | 800 | Apr 1, 2024 | Mar 1, 2024 00:00 | Apr 1, 2024 00:00 | 20003 | | 30005 | CONTRACT\_SCHEDULED | 800 | May 1, 2024 | Apr 1, 2024 00:00 | May 1, 2024 00:00 | 20003 | | 30006 | CONTRACT\_SCHEDULED | 800 | Jun 1, 2024 | May 1, 2024 00:00 | Jun 1, 2024 00:00 | 20003 | | 30007 | CONTRACT\_SCHEDULED | 800 | Jul 1, 2024 | Jun 1, 2024 00:00 | Jul 1, 2024 00:00 | 20003 | | 30008 | CONTRACT\_SCHEDULED | 800 | Aug 1, 2024 | Jul 1, 2024 00:00 | Aug 1, 2024 00:00 | 20003 | | 30009 | CONTRACT\_SCHEDULED | 800 | Sep 1, 2024 | Aug 1, 2024 00:00 | Sep 1, 2024 00:00 | 20003 | | 30010 | CONTRACT\_SCHEDULED | 800 | Oct 1, 2024 | Sep 1, 2024 00:00 | Oct 1, 2024 00:00 | 20003 | | 30011 | CONTRACT\_SCHEDULED | 800 | Nov 1, 2024 | Oct 1, 2024 00:00 | Nov 1, 2024 00:00 | 20003 | | 30011 | CONTRACT\_SCHEDULED | 800 | Dec 1, 2024 | Nov 1, 2024 00:00 | Dec 1, 2024 00:00 | 20003 | | 30011 | CONTRACT\_SCHEDULED | 800 | Jan 1, 2025 | Dec 1, 2024 00:00 | Jan 1, 2025 00:00 | 20003 | | 30012 | CONTRACT\_TRUEUP | 400 | Jan 1, 2025 | Dec 1, 2024 00:00 | Jan 1, 2025 00:00 | 20003 | Balances ledger | balances\_id | customer\_id | contract id | name | commit\_type | ledger\_entry\_id | ledger\_entry\_type | ledger\_entry\_timestamp | ledger\_entry\_amount | | ------------ | ------------ | ----------- | -------------------- | ------------ | ----------------- | --------------------------------------- | ------------------------ | --------------------- | | 50003 | 10003 | 20003 | postpaid\_commitment | POSTPAID | 60001 | postpaid\_initial\_balance | Jan 1, 2024 00:00 | 10,000 | | 50003 | 10003 | 20003 | postpaid\_commitment | POSTPAID | 60002 | postpaid\_automated\_invoice\_deduction | Feb 1, 2024 00:00 | -800 | | 50003 | 10003 | 20003 | postpaid\_commitment | POSTPAID | 60003 | postpaid\_automated\_invoice\_deduction | Mar 1, 2024 00:00 | -800 | | 50003 | 10003 | 20003 | postpaid\_commitment | POSTPAID | 60004 | postpaid\_automated\_invoice\_deduction | Apr 1, 2024 00:00 | -800 | | 50003 | 10003 | 20003 | postpaid\_commitment | POSTPAID | 60005 | postpaid\_automated\_invoice\_deduction | May 1, 2024 00:00 | -800 | | 50003 | 10003 | 20003 | postpaid\_commitment | POSTPAID | 60006 | postpaid\_automated\_invoice\_deduction | Jun 1, 2024 00:00 | -800 | | 50003 | 10003 | 20003 | postpaid\_commitment | POSTPAID | 60007 | postpaid\_automated\_invoice\_deduction | Jul 1, 2024 00:00 | -800 | | 50003 | 10003 | 20003 | postpaid\_commitment | POSTPAID | 60008 | postpaid\_automated\_invoice\_deduction | Aug 1, 2024 00:00 | -800 | | 50003 | 10003 | 20003 | postpaid\_commitment | POSTPAID | 60009 | postpaid\_automated\_invoice\_deduction | Sep 1, 2024 00:00 | -800 | | 50003 | 10003 | 20003 | postpaid\_commitment | POSTPAID | 60010 | postpaid\_automated\_invoice\_deduction | Oct 1, 2024 00:00 | -800 | | 50003 | 10003 | 20003 | postpaid\_commitment | POSTPAID | 60011 | postpaid\_automated\_invoice\_deduction | Nov 1, 2024 00:00 | -800 | | 50003 | 10003 | 20003 | postpaid\_commitment | POSTPAID | 60012 | postpaid\_automated\_invoice\_deduction | Dec 1, 2024 00:00 | -800 | | 50003 | 10003 | 20003 | postpaid\_commitment | POSTPAID | 60013 | postpaid\_automated\_invoice\_deduction | Jan 1, 2025 00:00 | -800 | | 50003 | 10003 | 20003 | postpaid\_commitment | POSTPAID | 60014 | postpaid\_trueup | Jan 1, 2025 00:00 | -400 | Using the table data, CloudNet recognizes the following revenue: * In month 1-12, Metronome issues a \$800 usage invoice * The merchant can recognize \$700 of postpaid commit revenue for CloudCompute each month * The merchant can recognize \$100 of postpaid commit revenue for CloudStorage each month * After month 12, Metronome issues a \$400 scheduled invoice for the postpaid true up * The merchant can recognize \$400 of postpaid commit revenue # Access in-app reports Source: https://docs.metronome.com/guides/reporting-insights/in-app-reporting Metronome can trigger custom and standard in-app reports to run against your Metronome data. Download these reports in a CSV format from the Reports tab in the Metronome app. To enable custom or standard reports, please contact us via the [Metronome support portal](https://support.metronome.com/). **DATA PROCESSING TIMES** While most reports generate within 1-2 hours, it can take up to 10 hours to generate larger reports. Reports are generated using data that updates once per day. Depending on when the underlying data updates, you may see stale data requiring you to trigger the report to run again. ## Standard reports Standard reports are pre-defined reports you can trigger to run from the Reports tab in the Metronome app. Once triggered, the report generates and you receive an email confirmation with a link to download the resulting report in the UI as a CSV file. **Included standard reports:** | Report name | Description | | ---------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Customers by created date | Returns all customers in your Metronome account. Useful for tracking customer growth over time. | | Contracts by created date | Returns all contracts across customers. Helpful for understanding contract volume and sales activity. | | Commits and credits by created date | Returns all prepaid commits and credits issued to customers. Useful for tracking commitment sales and credit grants. | | Invoices by status and by effective date | Returns all finalized invoices and line items, and effective billing period. Useful for accounts receivable and revenue recognition. | | Commit expiration ledger entries by month | Returns ledger entries for commits that expired during each month. Useful for tracking unused commitment balances and breakage revenue. | | True up invoices by effective date | Returns all true-up invoices. Useful for tracking end-of-period commitment reconciliation charges. | | Monthly revenue by product name and revenue category | Returns revenue totals broken down by product and category (e.g., on-demand, commit drawdown, overage) for each month. Useful for financial reporting and product performance analysis. | To trigger a standard report to run, visit the Reports tab in the Metronome app, select the report from the dropdown, enter filtering dates and click Generate Report. After a report completes, you'll receive an email confirmation with a link to download the resulting report in a CSV format from the Reports tab in the Metronome app. ## Custom reports **NOTE** Custom reports is a paid feature. If you're interested in learning more about this feature, contact [solutions@metronome.com](mailto:solutions@metronome.com). Custom reports provide a flexible mechanism to download custom Metronome datasets in a CSV format from the Reports tab in the Metronome app. The reporting engine can query the same data tables that are available via [Data Export](/guides/reporting-insights/data-export#data-availability). To create a custom report, follow these steps: 1. Contact us via the [Metronome support portal](https://support.metronome.com/) to request a custom report 2. Share detailed requirements about your reporting needs (e.g. end of month books close, customer cohorting, etc.) 3. Review sample data with the Metronome team 4. Approve the resulting data 5. Confirm how you want to trigger the reports (you can either trigger the report from the Metronome App or schedule via cron) To trigger a custom report to run, visit the Reports tab in the Metronome app, select the report from the dropdown, enter filtering dates and click Generate Report. After a report completes, you'll receive an email confirmation with a link to download the resulting report in a CSV format from the Reports tab in the Metronome app. ## In-app dashboards In-app dashboards are currently in beta. Contact us via the [Metronome support portal](https://support.metronome.com/) to have them turned on for your account. In-app dashboards provide Metronome clients with access to critical revenue and monetization metrics directly within the Metronome app. Rather than exporting data and building views externally, you can use these dashboards to monitor business performance, track key financial metrics, and explore customer-level details in real time. In-app dashboards **Included in-app dashboards:** | Dashboard | Description | | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Basic Revenue Overview | Provides monthly summaries of invoiced amounts, usage and subscription revenue, commit and credit metrics, and customer-level consumption details. | | Committed & Run Rate ARR Dashboard | Provides key financial metrics for consumption-based businesses, including Annual Recurring Revenue (ARR), Net Revenue Retention (NRR), Gross Revenue Retention (GRR), and logo movement. | | Filterable Customer List | Provides a flexible, filterable view of your customer list — built from common feature requests and designed to make it easier to search and sort by billing provider, spend, and other key attributes. | ### Committed & Run Rate ARR Dashboard The Committed & Run Rate ARR Dashboard surfaces the key financial metrics consumption businesses use to track growth and retention. The sections below describe how each metric is defined and computed. #### Metrics definitions **Committed ARR** Committed ARR measures the contractually committed revenue from customers, including usage commitments and scheduled charges. It is derived from `scheduled_charges` and `balances` in your Metronome data. * **Balances (commits and credits)**: Schedule items are unnested to extract individual commitment periods with their amounts and date ranges. ARR is calculated by dividing each schedule item's amount by its duration in days, then annualizing: `(amount / duration_days) × 365`. For CPU commits, amounts are converted to dollars using the corresponding rate card conversion. * **Scheduled charges**: Schedule items are unnested to sum the total amount per charge over its contract period (`starting_at` to `ending_before`). ARR is calculated by dividing the total amount by the duration in days, then annualizing. **Run Rate ARR** Run Rate ARR estimates annualized revenue based on actual usage and subscription revenue over a shorter, configurable window. For example, with a 3-month window: `run_rate_ARR = average monthly revenue across the last 3 months × 12`. Usage and subscription line items are used to calculate usage revenue. Methodology notes: * For customers with less than X months of history, whatever months are available are used to calculate the moving average MRR. * Run Rate ARR continues to be calculated for churned customers. If a customer's latest month's usage is `$0`, the run rate MRR is still the average across the last X months. #### ARR movement All metrics compare the current period to the base period (X months ago, configurable). * **New ARR**: ARR from customers who had `$0` ARR (or didn't exist) in the base period but have ARR `> $0` in the current period. * **Expansion ARR**: *Additional* ARR from existing customers whose ARR grew (current ARR `>` base period ARR). This is the difference between current and base. * **Contraction ARR**: *Lost* ARR from existing customers whose ARR decreased (base period ARR `>` current ARR, but current ARR `> $0`). This is the difference between base and current. * **Churned ARR**: The *full base period ARR* from customers who had ARR `> $0` in the base period but have `$0` ARR in the current period. **Net ARR Change** = New ARR + Expansion ARR − Contraction ARR − Churned ARR #### Revenue retention * **GRR (Gross Revenue Retention)**: The percentage of base period ARR retained, *excluding expansion*. * Formula: `retained_arr / starting_arr` * Where `retained_arr = min(current ARR, base ARR)` for each customer. * GRR `< 100%` means revenue was lost through contraction and churn. * **NRR (Net Revenue Retention)**: The percentage the base cohort's ARR grew to, *including expansion*. * Formula: `ending_arr_from_base_cohort / starting_arr` * Where `ending_arr_from_base_cohort` is the current ARR for customers who existed in the base period. * NRR `> 100%` means expansion exceeded contraction and churn. * NRR `< 100%` means contraction and churn exceeded expansion. #### Customer/logo movement * **New customers**: Customers who had `$0` ARR (or didn't exist) in the base period but have ARR `> $0` in the current period. * **Expanding customers**: Existing customers whose ARR grew (current ARR `>` base period ARR). * **Retained customers**: Existing customers whose ARR stayed exactly the same (current ARR `=` base period ARR). * **Contracting customers**: Existing customers whose ARR decreased but still have ARR `> $0` (base ARR `>` current ARR `> $0`). * **Churned customers**: Customers who had ARR `> $0` in the base period but have `$0` ARR in the current period. * **Active customers**: Total count of customers with ARR `> $0` in the current period, regardless of base period status. #### Available filters **Committed ARR tab** These filters apply to the combined scheduled charges and commits dataset. | Filter | Type | Default | Behavior | | ---------------------------------- | ----------- | ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | | Exclude customer | Multiselect | *(none)* | Removes selected customers. | | Exclude contract | Multiselect | *(none)* | Removes selected contracts. Rows without a contract (e.g., standalone scheduled charges) are preserved. | | Exclude commit type | Multiselect | `credit` | Removes selected commit types (e.g., `credit`, `prepaid`, `postpaid`). Scheduled charges without a commit type are preserved. | | Exclude commit shorter than (days) | Number | `30` | Excludes commits/charges with duration below this threshold. Always active. | | Exclude non-recurring charge | Checkbox | Off | When checked, keeps only rows with a recurring schedule. Removes fees that would occur only once. | | Exclude commit not invoiced | Checkbox | Off | When checked, keeps only commits that have associated invoice schedule items. | | Select rate card | Multiselect | *(none — all included)* | When populated, restricts to only the selected rate card(s). | | Lookback period (months) | Number | `12` | Controls how many months of history are used for ARR movement, NRR/GRR, and customer movement calculations. Shared with the Run Rate tab. | **Run Rate ARR tab** These filters apply to the usage-based revenue dataset. A hardcoded filter also restricts data to **completed months only** (month `<` current month start). | Filter | Type | Default | Behavior | | ------------------------ | ----------- | ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | | Exclude customer | Multiselect | *(none)* | Removes selected customers. | | Exclude product | Multiselect | *(none)* | Removes selected products. | | Exclude product type | Multiselect | *(none)* | Removes selected product types. | | Exclude rev rec type | Multiselect | `credit_drawdown` | Removes selected revenue recognition types (e.g., `credit_drawdown`, `prepaid_commit_drawdown`, `postpaid_commit_drawdown`, `on_demand_usage`). | | Customers without commit | Checkbox | Off | When checked, excludes customers who have any non-credit commits. Useful for isolating pure on-demand customers. | | Select rate card | Multiselect | *(none — all included)* | When populated, restricts to only the selected rate card(s). | | Average last X months | Number | `3` | Number of trailing completed months used to compute the run rate. Monthly revenue is averaged over this window, then annualized. | | Lookback period (months) | Number | `12` | Shared with the Committed ARR tab. Controls ARR movement, NRR/GRR, and customer movement history window. | #### Caveats * Only contract data and finalized invoices are used. * All invoices are prorated by day, so invoices spanning multiple months are split across those months. * Non-USD fiat currencies are not supported. # API quickstart Source: https://docs.metronome.com/api-reference/api-quickstart Get connected to Metronome's API and make your first call in minutes. ## Create an API token 1. Log into the Metronome App [here](https://app.metronome.com/). 2. Navigate to **Developer → API tokens → Add.** 3. Create a new token and give it a descriptive name. 4. Make sure to copy the token to a secure location before clicking Done. > Learn more about Metronome API authentication [here](/api-reference/authorization). ## Install the Metronome SDK 1. Install the SDK in your environment. ```bash Python theme={null} pip install --pre metronome-sdk ``` ```bash Node theme={null} npm install @metronome/sdk ``` ```bash Ruby theme={null} gem install metronome-sdk ``` ```bash Go theme={null} go get -u 'github.com/Metronome-Industries/metronome-go' ``` 2. Configure the SDK by passing in your API key . By default, the SDK looks for the API key under the environment variable METRONOME\_BEARER\_TOKEN. ```python Python theme={null} from metronome import Metronome client = Metronome( # Defaults to os.environ.get("METRONOME_BEARER_TOKEN") if omitted bearer_token="My bearer token", ) ``` ```javascript Node theme={null} import Metronome from "@metronome/sdk"; const client = new Metronome({ // Defaults to os.environ.get("METRONOME_BEARER_TOKEN") if omitted bearerToken: "My bearer token", }); ``` ```ruby Ruby theme={null} require "bundler/setup" require "metronome_sdk" metronome = MetronomeSDK::Client.new( bearer_token: "My Bearer Token" # defaults to ENV["METRONOME_BEARER_TOKEN"] ) ``` ```go Go theme={null} package main import ( "context" "fmt" "github.com/Metronome-Industries/metronome-go" "github.com/Metronome-Industries/metronome-go/option" ) func main() { client := metronome.NewClient( option.WithBearerToken("My bearer token"), // defaults to os.LookupEnv("METRONOME_BEARER_TOKEN") if omitted ) } ``` > Learn more about the Metronome SDK [here](/guides/get-started/developer-sdks). ## Test the API 1. Make a test API call - for example, list the customers in your Metronome account. This will work even if your customer list is empty. ```python Python theme={null} response = client.v1.customers.list() print("✓ Connected to Metronome!") if response.data: customer = response.data[0] print(f" First customer: {customer.name}") else: print(" No customers found.") ``` ```javascript Node theme={null} const resp = await client.v1.customers.list(); console.log('✓ Connected to Metronome!'); if (resp.data && resp.data.length > 0) { console.log(` First customer: ${resp.data[0].name}`); } else { console.log(' No customers found.'); } ``` ```ruby Ruby theme={null} resp = client.v1.customers.list puts '✓ Connected to Metronome!' if resp.data && !resp.data.empty? puts " First customer: #{resp.data.first.name}" else puts ' No customers found.' end ``` ```go Go theme={null} resp, err := client.V1.Customers.List(context.TODO(), metronome.V1CustomerListParams{}) if err != nil { return fmt.Errorf("failed to list customers: %w", err) } fmt.Println("✓ Connected to Metronome!") if len(resp.Data) > 0 { fmt.Printf(" First customer: %s\n", resp.Data[0].Name) } else { fmt.Println(" No customers found.") } ``` **Success!** You're now connected to Metronome. Once connected, you can track usage, set pricing, and automate invoicing. ## Next Steps * **Send your first usage event:** track customer usage in real-time [View guide →](/guides/get-started/core-concepts/send-usage-events) * Check out the implementation guides [View guide →](/guides/pricing-packaging/billing-model-guides/guides-home) # API Authentication Source: https://docs.metronome.com/api-reference/authentication Metronome’s API uses bearer tokens to authenticate requests. This page walks through how to create and manage tokens. ## **Create a token** API tokens can be created through the Metronome app. 1. Click on **Developer** in the navigation bar. 2. Click on **API tokens** in the horizontal navigation bar on the resulting page. 3. Click on the **+ Add** button. 4. Enter a descriptive name for the token and click **Create new token.** 5. Copy the token string to a secure location before clicking **Done.** **SAVE YOUR TOKEN** Be sure to save the token you create. You cannot view the full token again. Create as many tokens as is useful, providing descriptive names for each. The token's name is associated with API calls made using it, which can be helpful when tracking changes and requests in the Metronome's [audit logs](../guides/platform-configuration/audit-logs). ## Using tokens When making API calls, provide the token using the `Authorization` header. If using the SDK, the SDK will look for the API key under the environment variable `METRONOME_BEARER_TOKEN` by default. See **SDK documentation** for more details. ```python Python theme={null} from metronome import Metronome client = Metronome( # Defaults to os.environ.get("METRONOME_BEARER_TOKEN") if omitted bearer_token="My bearer token", ) ``` ```javascript Node theme={null} import Metronome from "@metronome/sdk"; const client = new Metronome({ // Defaults to os.environ.get("METRONOME_BEARER_TOKEN") if omitted bearerToken: "My bearer token", }); ``` ```ruby Ruby theme={null} require "bundler/setup" require "metronome_sdk" metronome = MetronomeSDK::Client.new( bearer_token: "My Bearer Token" # defaults to ENV["METRONOME_BEARER_TOKEN"] ) ``` ```go Go theme={null} package main import ( "context" "github.com/Metronome-Industries/metronome-go" "github.com/Metronome-Industries/metronome-go/option" ) func main() { client := metronome.NewClient( option.WithBearerToken("My bearer token"), // defaults to os.LookupEnv("METRONOME_BEARER_TOKEN") if omitted ) } ``` If your token is valid, you’ll receive a JSON payload from the API—either data (if the endpoint returns records) or a 404 JSON error object if no resources are found. If your token is invalid, you’ll receive a 401 or 403 error. See API status codes for more detail. ## Postman Setup If you use Postman: 1. Import the [Metronome OpenAPI spec](https://api.metronome.com/v1/docs/openapi). 2. In the collection settings, set **Authorization** to **Bearer Token** and use `{{api_token}}` as the token. 3. Add `api_token` to your Postman environment variables. See our [Postman guide](./postman) for step-by-step instructions. ## Permissions By default, Metronome API tokens will retain the same permissions as the user that created them. Metronome API tokens can also be limited in scope to reduce risk and follow the principle of least privilege. Metronome supports scoping by: * Access level (e.g., read-only) * Environment (e.g., sandbox only) * Endpoint (e.g., only getCustomers) To adjust permissions, contact us via the [Metronome support portal](https://support.metronome.com/). ## Archiving tokens Metronome enables archiving tokens that are no longer in use. To do this, simply hit the Trash icon next to the relevant token in the Metronome UI. This action cannot be undone. **BEST PRACTICES** Follow security best practices by removing unused tokens and regularly rotating tokens in use. # Archive a billable metric Source: https://docs.metronome.com/api-reference/billable-metrics/archive-a-billable-metric /openapi.json post /v1/billable-metrics/archive Use this endpoint to retire billable metrics that are no longer used. After a billable metric is archived, that billable metric can no longer be used in any new Products to define how that product should be metered. If you archive a billable metric that is already associated with a Product, the Product will continue to function as usual, metering based on the definition of the archived billable metric. Archived billable metrics will be returned on the `getBillableMetric` and `listBillableMetrics` endpoints with a populated `archived_at` field. # Create a billable metric Source: https://docs.metronome.com/api-reference/billable-metrics/create-a-billable-metric /openapi.json post /v1/billable-metrics/create Create billable metrics programmatically with this endpoint—an essential step in configuring your pricing and packaging in Metronome. A billable metric is a customizable query that filters and aggregates events from your event stream. These metrics are continuously tracked as usage data enters Metronome through the ingestion pipeline. The ingestion process transforms raw usage data into actionable pricing metrics, enabling accurate metering and billing for your products. ### Use this endpoint to: - Create individual or multiple billable metrics as part of a setup workflow. - Automate the entire pricing configuration process, from metric creation to customer contract setup. - Define metrics using either standard filtering/aggregation or a custom SQL query. ### Key response fields: - The ID of the billable metric that was created - The created billable metric will be available to be used in Products, usage endpoints, and alerts. ### Usage guidelines: - Metrics defined using standard filtering and aggregation are Streaming billable metrics, which have been optimized for ultra low latency and high throughput workflows. - Use SQL billable metrics if you require more flexible aggregation options. # Get a billable metric Source: https://docs.metronome.com/api-reference/billable-metrics/get-a-billable-metric /openapi.json get /v1/billable-metrics/{billable_metric_id} Retrieves the complete configuration for a specific billable metric by its ID. Use this to review billable metric setup before associating it with products. Returns the metric's `name`, `event_type_filter`, `property_filters`, `aggregation_type`, `aggregation_key`, `group_keys`, `custom fields`, and `SQL query` (if it's a SQL billable metric). Important: - Archived billable metrics will include an `archived_at` timestamp; they no longer process new usage events but remain accessible for historical reference. # Get billable metrics for a customer Source: https://docs.metronome.com/api-reference/billable-metrics/get-billable-metrics-for-a-customer /openapi.json get /v1/customers/{customer_id}/billable-metrics Get all billable metrics available for a specific customer. Supports pagination and filtering by current plan status or archived metrics. Use this endpoint to see which metrics are being tracked for billing calculations for a given customer. # List all billable metrics Source: https://docs.metronome.com/api-reference/billable-metrics/list-all-billable-metrics /openapi.json get /v1/billable-metrics Retrieves all billable metrics with their complete configurations. Use this for programmatic discovery and management of billable metrics, such as associating metrics to products and auditing for orphaned or archived metrics. Important: Archived metrics are excluded by default; use `include_archived`=`true` parameter to include them. # Update a billable metric Source: https://docs.metronome.com/api-reference/billable-metrics/update-a-billable-metric /openapi.json put /v1/billable-metrics/{billable_metric_id} Updates only the display name of an existing billable metric. Use this to correct mistakes or apply standardized naming conventions across all billable metrics. Returns the billable metric ID to confirm the update. Important: Only the name can be modified via this endpoint; configurations cannot be changed after creation. #### Example workflow: If you need to make changes to a streaming billable metric, for example, Metronome supports easily rolling out these changes using a simple workflow: 1. Duplicate the billable metric 2. Make required changes 3. Save the metric 4. Navigate to the product you have associated with the incorrect metric 5. Schedule the product to reference the newly created metric on the appropriate date # Amend a contract Source: https://docs.metronome.com/api-reference/contracts/amend-a-contract /openapi.json post /v1/contracts/amend Amendments will be replaced by Contract editing. New clients should implement using the `editContract` endpoint. Read more about the migration to contract editing [here](/guides/implement-metronome/migrate-amendments-to-edits/) and contact us via the [Metronome support portal](https://support.metronome.com/) for more details. Once contract editing is enabled, access to this endpoint will be removed. # Archive a contract Source: https://docs.metronome.com/api-reference/contracts/archive-a-contract /openapi.json post /v1/contracts/archive Permanently end and archive a contract along with all its terms. Any draft invoices will be canceled, and all upcoming scheduled invoices will be voided–also all finalized invoices can optionally be voided. Use this in the event a contract was incorrectly created and needed to be removed from a customer. #### Impact on commits and credits: When archiving a contract, all associated commits and credits are also archived. For prepaid commits with active segments, Metronome automatically generates expiration ledger entries to close out any remaining balances, ensuring accurate accounting of unused prepaid amounts. These ledger entries will appear in the commit's transaction history with type `PREPAID_COMMIT_EXPIRATION`. #### Archived contract visibility: Archived contracts remain accessible for historical reporting and audit purposes. They can be retrieved using the `ListContracts` endpoint by setting the `include_archived` parameter to `true` or in the Metronome UI when the "Show archived" option is enabled. # Create a contract Source: https://docs.metronome.com/api-reference/contracts/create-a-contract /openapi.json post /v1/contracts/create Contracts define a customer's products, pricing, discounts, access duration, and billing configuration. Contracts serve as the central billing agreement for both PLG and Enterprise customers. You can automatically grant customers access to your products and services directly from your product or CRM. ### Use this endpoint to: - PLG onboarding: Automatically provision new self-serve customers with contracts when they sign up. - Enterprise sales: Push negotiated contracts from Salesforce with custom pricing and commitments - Promotional pricing: Implement time-limited discounts and free trials through overrides ### Key components: #### Contract Term and Billing Schedule - Set contract duration using `starting_at` and `ending_before` fields. PLG contracts typically use perpetual agreements (no end date), while Enterprise contracts have fixed end dates which can be edited over time in the case of co-term upsells. #### Rate Card If you are offering usage based pricing, you can set a rate card for the contract to reference through `rate_card_id` or `rate_card_alias`. The rate card is a store of all of your usage based products and their centralized pricing. Any new products or price changes on the rate card can be set to automatically propagate to all associated contracts - this ensures consistent pricing and product launches flow to contracts without manual updates and migrations. The `usage_statement_schedule` determines the cadence on which Metronome will finalize a usage invoice for the customer. This defaults to monthly on the 1st, with options for custom dates, quarterly, or annual cadences. Note: Most usage based billing companies align usage statements to be evaluated aligned to the first of the month. Read more about [Rate Cards](https://docs.metronome.com/pricing-packaging/create-manage-rate-cards/). #### Overrides and discounts Customize pricing on the contract through time-bounded overrides that can target specific products, product families, or complex usage scenarios. Overrides enable two key capabilities: - Discounts: Apply percentage discounts, fixed rate reductions, or quantity-based pricing tiers - Entitlements: Provide special pricing or access to specific products for negotiated deals Read more about [Contract Overrides](https://docs.metronome.com/manage-product-access/add-contract-override/). #### Commits and Credits Using commits, configure prepaid or postpaid spending commitments where customers promise to spend a certain amount over the contract period paid in advance or in arrears. Use credits to provide free spending allowances. Under the hood these are the same mechanisms, however, credits are typically offered for free (SLA or promotional) or as a part of an allotment associated with a Subscription. In Metronome, you can set commits and credits to only be applicable for a subset of usage. Use `applicable_product_ids` or `applicable_product_tags` to create product or product-family specific commits or credits, or you can build complex boolean logic specifiers to target usage based on pricing and presentation group values using `override_specifiers`. These objects can also also be configured to have a recurrence schedule to easily model customer packaging which includes recurring monthly or quarterly allotments. Commits support rollover settings (`rollover_fraction`) to transfer unused balances between contract periods, either entirely or as a percentage. Read more about [Credits and Commits](https://docs.metronome.com/pricing-packaging/apply-credits-commits/). #### Subscriptions You can add a fixed recurring charge to a contract, like monthly licenses or seat-based fees, using the subscription charge. Subscription charges are defined on your rate card and you can select which subscription is applicable to add to each contract. When you add a subscription to a contract you need to: - Define whether the subscription is paid for in-advance or in-arrears (`collection_schedule`) - Define the proration behavior (`proration`) - Specify an initial quantity (`initial_quantity`) - Define which subscription rate on the rate card should be used (`subscription_rate`) Read more about [Subscriptions](https://docs.metronome.com/manage-product-access/create-subscription/). #### Scheduled Charges Set up one-time, recurring, or entirely custom charges that occur on specific dates, separate from usage-based billing or commitments. These can be used to model non-recurring platform charges or professional services. #### Threshold Billing Metronome allows you to configure automatic billing triggers when customers reach spending thresholds to prevent fraud and manage risk. You can use `spend_threshold_configuration` to trigger an invoice to cover current charges whenever the threshold is reached or you can ensure the customer maintains a minimum prepaid balance using the `prepaid_balance_configuration`. Read more about [Spend Threshold](https://docs.metronome.com/manage-product-access/spend-thresholds/) and [Prepaid Balance Thresholds](https://docs.metronome.com/manage-product-access/prepaid-balance-thresholds/). ### Usage guidelines: - You can always [Edit Contracts](https://docs.metronome.com/manage-product-access/edit-contract/) after it has been created, using the `editContract` endpoint. Metronome keeps track of all edits, both in the audit log and over the `getEditHistory` endpoint. - Customers in Metronome can have multiple concurrent contracts at one time. Use `usage_filters` to route the correct usage to each contract. [Read more about usage filters](https://docs.metronome.com/manage-product-access/provision-customer/#create-a-usage-filter). # Create historical invoices Source: https://docs.metronome.com/api-reference/contracts/create-historical-invoices /openapi.json post /v1/contracts/createHistoricalInvoices Create historical usage invoices for past billing periods on specific contracts. Use this endpoint to generate retroactive invoices with custom usage line items, quantities, and date ranges. Supports preview mode to validate invoice data before creation. Ideal for billing migrations or correcting past billing periods. # Edit a contract Source: https://docs.metronome.com/api-reference/contracts/edit-a-contract /openapi.json post /v2/contracts/edit The ability to edit a contract helps you react quickly to the needs of your customers and your business. ### Use this endpoint to: - Encode mid-term commitment and discount changes - Fix configuration mistakes and easily roll back packaging changes ### Key response fields: - The `id` of the edit - Complete edit details. For example, if you edited the contract to add new overrides and credits, you will receive the IDs of those overrides and credits in the response. ### Usage guidelines: - When you edit a contract, any draft invoices update immediately to reflect that edit. Finalized invoices remain unchanged - you must void and regenerate them in the UI or API to reflect the edit. - Contract editing must be enabled to use this endpoint. Contact us via the [Metronome support portal](https://support.metronome.com/) to learn more. # Get a contract (v1) Source: https://docs.metronome.com/api-reference/contracts/get-a-contract-v1 /openapi.json post /v1/contracts/get This is the v1 endpoint to get a contract. New clients should implement using the v2 endpoint. # Get a contract (v2) Source: https://docs.metronome.com/api-reference/contracts/get-a-contract-v2 /openapi.json post /v2/contracts/get Gets the details for a specific contract, including contract term, rate card information, credits and commits, and more. ### Use this endpoint to: - Check the duration of a customer's current contract - Get details on contract terms, including access schedule amounts for commitments and credits - Understand the state of a contract at a past time. As you can evolve the terms of a contract over time through editing, use the `as_of_date` parameter to view the full contract configuration as of that point in time. ### Usage guidelines: - Optionally, use the `include_balance` and `include_ledger` fields to include balances and ledgers in the credit and commit responses. Using these fields will cause the query to be slower. # Get contract edit history Source: https://docs.metronome.com/api-reference/contracts/get-contract-edit-history /openapi.json post /v2/contracts/getEditHistory List all the edits made to a contract over time. In Metronome, you can edit a contract at any point after it's created to fix mistakes or reflect changes in terms. Metronome stores a full history of all edits that were ever made to a contract, whether through the UI, `editContract` endpoint, or other endpoints like `updateContractEndDate`. ### Use this endpoint to: - Understand what changes were made to a contract, when, and by who ### Key response fields: - An array of every edit ever made to the contract - Details on each individual edit - for example showing that in one edit, a user added two discounts and incremented a subscription quantity. # Get subscription quantity history Source: https://docs.metronome.com/api-reference/contracts/get-subscription-quantity-history /openapi.json post /v1/contracts/getSubscriptionQuantityHistory Get the history of subscription quantities and prices over time for a given `subscription_id`. This endpoint can be used to power an in-product experience where you show a customer their historical changes to seat count. Future changes are not included in this endpoint - use the `getContract` endpoint to view the future scheduled changes to a subscription's quantity. Subscriptions are used to model fixed recurring fees as well as seat-based recurring fees. To model changes to the number of seats in Metronome, you can increment or decrement the quantity on a subscription at any point in the past or future. # Get subscription seats history Source: https://docs.metronome.com/api-reference/contracts/get-subscription-seats-history /openapi.json post /v1/contracts/getSubscriptionSeatsHistory Get the history of subscription seats schedule over time for a given `subscription_id`. This endpoint provides information about seat assignments and total quantities for different time periods, allowing you to track how seat assignments have changed over time. ### Use this endpoint to: - Track changes to seat assignments over time - Get seat schedule for a specific date using the `covering_date` parameter - Get seat schedule history with optional date range filtering using `starting_at` and `ending_before` ### Key response fields: - data: array of seat schedule entries with time periods, quantity, and assignments - next_page: cursor for pagination to retrieve additional results ### Usage guidelines: - Use `covering_date` to get the active seats for a specific point in time. `covering_date` cannot be used with `starting_at` or `ending_before`. - Use `starting_at` and `ending_before` to filter results by time range. `starting_at` and `ending_before` cannot be used with `covering_date`. - Maximum limit is 10 seat schedule entries per request - Results are ordered by `starting_at` timestamp # Get the rate schedule for a contract Source: https://docs.metronome.com/api-reference/contracts/get-the-rate-schedule-for-a-contract /openapi.json post /v1/contracts/getContractRateSchedule For a specific customer and contract, get the rates at a specific point in time. This endpoint takes the contract's rate card into consideration, including scheduled changes. It also takes into account overrides on the contract. For example, if you want to show your customer a summary of the prices they are paying, inclusive of any negotiated discounts or promotions, use this endpoint. This endpoint only returns rates that are entitled. # List customer contracts (v1) Source: https://docs.metronome.com/api-reference/contracts/list-customer-contracts-v1 /openapi.json post /v1/contracts/list Retrieves all contracts for a specific customer, including pricing, terms, credits, and commitments. Use this to view a customer's contract history and current agreements for billing management. Returns contract details with optional ledgers and balance information. ⚠️ Note: This is the legacy v1 endpoint - new integrations should use the v2 endpoint for enhanced features. # List customer contracts (v2) Source: https://docs.metronome.com/api-reference/contracts/list-customer-contracts-v2 /openapi.json post /v2/contracts/list For a given customer, lists all of their contracts in chronological order. ### Use this endpoint to: - Check if a customer is provisioned with any contract, and at which tier - Check the duration and terms of a customer's current contract - Power a page in your end customer experience that shows the customer's history of tiers (e.g. this customer started out on the Pro Plan, then downgraded to the Starter plan). ### Usage guidelines: Use the `starting_at`, `covering_date`, and `include_archived` parameters to filter the list of returned contracts. For example, to list only currently active contracts, pass `covering_date` equal to the current time. # Set a contract usage filter Source: https://docs.metronome.com/api-reference/contracts/set-a-contract-usage-filter /openapi.json post /v1/contracts/setUsageFilter If a customer has multiple contracts with overlapping rates, the usage filter routes usage to the appropriate contract based on a predefined group key. As an example, imagine you have a customer associated with two projects. Each project is associated with its own contract. You can create a usage filter with group key `project_id` on each contract, and route usage for `project_1` to the first contract and `project_2` to the second contract. ### Use this endpoint to: - Support enterprise contracting scenarios where multiple contracts are associated to the same customer with the same rates. - Update the usage filter associated with the contract over time. ### Usage guidelines: To use usage filters, the `group_key` must be defined on the billable metrics underlying the rate card on the contracts. # Update invoice issue date Source: https://docs.metronome.com/api-reference/contracts/update-invoice-issue-date /openapi.json post /v1/contracts/updateInvoiceIssueDate Updates the issue date of a specific DRAFT invoice within a contract. Use this endpoint to reschedule when an invoice should be issued without affecting future billing cycles or the underlying contract terms. Only works with invoices still in DRAFT status, and the new issue date cannot be later than the contract's end date. ### Usage guidelines: This only changes the individual invoice's issue date - it does not modify the recurring invoice schedule of associated charges or commits. To update both the issue date and future billing schedule, use the 'edit contract' or 'edit commit' endpoints instead. # Update the contract end date Source: https://docs.metronome.com/api-reference/contracts/update-the-contract-end-date /openapi.json post /v1/contracts/updateEndDate Update or add an end date to a contract. Ending a contract early will impact draft usage statements, truncate any terms, and remove upcoming scheduled invoices. Moving the date into the future will only extend the contract length. Terms and scheduled invoices are not extended. In-advance subscriptions will not be extended. Use this if a contract's end date has changed or if a perpetual contract ends. # Add a manual balance entry Source: https://docs.metronome.com/api-reference/credits-and-commits/add-a-manual-balance-entry /openapi.json post /v1/contracts/addManualBalanceLedgerEntry Manually adjust the available balance on a commit or credit. This entry is appended to the commit ledger as a new event. Optionally include a description that provides the reasoning for the entry. ### Use this endpoint to: - Address incorrect usage burn-down caused by malformed usage or invalid config - Decrease available balance to account for outages where usage may have not been tracked or sent to Metronome - Issue credits to customers in the form of increased balance on existing commit or credit ### Usage guidelines: Manual ledger entries can be extremely useful for resolving discrepancies in Metronome. However, most corrections to inaccurate billings can be modified upstream of the commit, whether that is via contract editing, rate editing, or other actions that cause an invoice to be recalculated. # Archive a commit Source: https://docs.metronome.com/api-reference/credits-and-commits/archive-a-commit /openapi.json post /v2/contracts/commits/archive Archive a contract-level or customer-level commit. Use this endpoint to deactivate a commit while preserving historical records. You will not be able to archive a commit until all of the finalized usage invoices the commit has been applied to are voided, and all of the finalized invoices for commit payment have been voided. Example workflow: The customer was provisioned a prepaid commit erroneously. It was applied to their most recent finalized usage invoice. - First, void the finalized invoice that the commit was applied to. Also, void the finalized invoice associated with the commit payment. - Then, use the archiveCommit endpoint to deactivate the commit. - Finally, regenerate the voided invoice. The invoice will be regenerated without the application of the commit, which has now been archived. ### Usage guidelines: - Once a commit has been archived, it will no longer appear by default on the endpoints `listCustomerCommits` or `listCustomerBalances`. Use the `include_archived` parameter to choose to fetch the details. - Once a commit has been archived, it has a null ledger and 0 remaining balance. - Archiving a commit fully deactivates the entire access schedule. If you want to reduce the amount granted in a commit, consider editing the access schedule using the `editCommit` endpoint, or adding a manual ledger entry using the `addManualBalanceLedgerEntry` endpoint. # Archive a credit Source: https://docs.metronome.com/api-reference/credits-and-commits/archive-a-credit /openapi.json post /v2/contracts/credits/archive Archive a contract-level or customer-level credit. Use this endpoint to deactivate a credit while preserving historical records. You will not be able to archive a credit until all of the finalized invoices the credit has been applied to are voided. Example workflow: The customer was granted a free credit erroneously. It was applied to their most recent finalized invoice. - First, void the finalized invoice that the credit was applied to. - Then, use the archiveCredit endpoint to deactivate the credit. - Finally, regenerate the voided invoice. The invoice will be regenerated without the application of the credit, which has now been archived. ### Usage guidelines: - Once a credit has been archived, it will no longer appear by default on the endpoints `listCustomerCredits` or `listCustomerBalances`. Use the `include_archived` parameter to choose to fetch the details. - Once a credit has been archived, it has a null ledger and 0 remaining balance. - Archiving a credit fully deactivates the entire access schedule. If you want to reduce the amount granted in a credit, consider editing the access schedule using the `editCredit` endpoint, or adding a manual ledger entry using the `addManualBalanceLedgerEntry` endpoint. # Create a commit Source: https://docs.metronome.com/api-reference/credits-and-commits/create-a-commit /openapi.json post /v1/contracts/customerCommits/create ⚠️ For most contract amendments, use `contracts/edit` directly. Use this endpoint only for cross-contract or enterprise-wide commits. Creates customer-level commits that establish spending commitments for customers across their Metronome usage. Commits represent contracted spending obligations that can be either prepaid (paid upfront) or postpaid (billed later). Note: In most cases, you should add commitments directly to customer contracts using the contract/create or contract/edit APIs. ### Use this endpoint to: Use this endpoint when you need to establish customer-level spending commitments that can be applied across multiple contracts or scoped to specific contracts. Customer-level commits are ideal for: - Enterprise-wide minimum spending agreements that span multiple contracts - Multi-contract volume commitments with shared spending pools - Cross-contract discount tiers based on aggregate usage #### Commit type Requirements: - You must specify either "prepaid" or "postpaid" as the commit type: - Prepaid commits: Customer pays upfront; invoice_schedule is optional (if omitted, creates a commit without an invoice) - Postpaid commits: Customer pays when the commitment expires (the end of the access_schedule); invoice_schedule is required and must match access_schedule totals. #### Billing configuration: - invoice_contract_id is required for postpaid commits and for prepaid commits with billing (only optional for free prepaid commits) unless do_not_invoice is set to true - For postpaid commits: access_schedule and invoice_schedule must have matching amounts - For postpaid commits: only one schedule item is allowed in both schedules. #### Scoping flexibility: Customer-level commits can be configured in a few ways: - Contract-specific: Use the `applicable_contract_ids` field to limit the commit to specific contracts - Cross-contract: Leave `applicable_contract_ids` empty to allow the commit to be used across all of the customer's contracts #### Product targeting: Commits can be scoped to specific products using applicable_product_ids, applicable_product_tags, or specifiers, or left unrestricted to apply to all products. #### Priority considerations: When multiple commits are applicable, the one with the lower priority value will be consumed first. If there is a tie, contract level commits and credits will be applied before customer level commits and credits. Plan your priority scheme carefully to ensure commits are applied in the desired order. ### Usage guidelines: ⚠️ Preferred Alternative: In most cases, you should add commits directly to contracts using the create contract or edit contract APIs instead of creating customer-level commits. Contract-level commits provide better organization and are the recommended approach for standard use cases. # Create a credit Source: https://docs.metronome.com/api-reference/credits-and-commits/create-a-credit /openapi.json post /v1/contracts/customerCredits/create ⚠️ For most contract amendments, use `contracts/edit` directly. Use this endpoint only for cross-contract or enterprise-wide commits. Creates customer-level credits that provide spending allowances or free credit balances for customers across their Metronome usage. Note: In most cases, you should add credits directly to customer contracts using the contract/create or contract/edit APIs. ### Use this endpoint to: Use this endpoint when you need to provision credits directly at the customer level that can be applied across multiple contracts or scoped to specific contracts. Customer-level credits are ideal for: - Customer onboarding incentives that apply globally - Flexible spending allowances that aren't tied to a single contract - Migration scenarios where you need to preserve existing customer balances #### Scoping flexibility: Customer-level credits can be configured in two ways: - Contract-specific: Use the applicable_contract_ids field to limit the credit to specific contracts - Cross-contract: Leave applicable_contract_ids empty to allow the credit to be used across all of the customer's contracts #### Product Targeting: Credits can be scoped to specific products using `applicable_product_ids` or `applicable_product_tags`, or left unrestricted to apply to all products. #### Priority considerations: When multiple credits are applicable, the one with the lower priority value will be consumed first. If there is a tie, contract level commits and credits will be applied before customer level commits and credits. Plan your priority scheme carefully to ensure credits are applied in the desired order. #### Access Schedule Required: You must provide an `access_schedule` that defines when and how much credit becomes available to the customer over time. This usually is aligned to the contract schedule or starts immediately and is set to expire in the future. ### Usage Guidelines: ⚠️ Preferred Alternative: In most cases, you should add credits directly to contracts using the contract/create or contract/edit APIs instead of creating customer-level credits. Contract-level credits provide better organization, and are easier for finance teams to recognize revenue, and are the recommended approach for most use cases. # Disable trueup for commit Source: https://docs.metronome.com/api-reference/credits-and-commits/disable-trueup-for-commit /openapi.json post /v1/contracts/commits/disableTrueup Disable the true-up invoice for a postpaid commit. If used, the true-up invoice will not be generated. For postpaid commits, usage during the access period is paid for in arrears. If the total amount paid during the access period is less than the committed amount, there's a final true-up invoice on the invoice_date. # Edit a commit Source: https://docs.metronome.com/api-reference/credits-and-commits/edit-a-commit /openapi.json post /v2/contracts/commits/edit Edit specific details for a contract-level or customer-level commit. Use this endpoint to modify individual commit access schedules, invoice schedules, applicable products, invoicing contracts, or other fields. ### Usage guidelines: - As with all edits in Metronome, draft invoices will reflect the edit immediately, while finalized invoices are untouched unless voided and regenerated. - If a commit's invoice schedule item is associated with a finalized invoice, you cannot remove or update the invoice schedule item. - If a commit's invoice schedule item is associated with a voided invoice, you cannot remove the invoice schedule item. - You cannot remove an commit access schedule segment that was applied to a finalized invoice. You can void the invoice beforehand and then remove the access schedule segment. # Edit a credit Source: https://docs.metronome.com/api-reference/credits-and-commits/edit-a-credit /openapi.json post /v2/contracts/credits/edit Edit details for a contract-level or customer-level credit. ### Use this endpoint to: - Extend the duration or the amount of an existing free credit like a trial - Modify individual credit access schedules, applicable products, priority, or other fields. ### Usage guidelines: - As with all edits in Metronome, draft invoices will reflect the edit immediately, while finalized invoices are untouched unless voided and regenerated. - You cannot remove an access schedule segment that was applied to a finalized invoice. You can void the invoice beforehand and then remove the access schedule segment. # Get the net balance of a customer Source: https://docs.metronome.com/api-reference/credits-and-commits/get-the-net-balance-of-a-customer /openapi.json post /v1/contracts/customerBalances/getNetBalance Retrieve the combined current balance across any grouping of credits and commits for a customer in a single API call. - Display real-time available balance to customers in billing dashboards - Build finance dashboards showing credit utilization across customer segments - Validate expected vs. actual balance during billing reconciliation ### Key response fields: - `balance`: The combined net balance available to use at this moment across all matching commits and credits - `credit_type_id`: The credit type (fiat or custom pricing unit) the balance is denominated in ### Filtering options: Balance filters allow you to scope the calculation to specific subsets of commits and credits. When using multiple filter objects, they are OR'd together — if a commit or credit matches any filter, it's included in the net balance. Within a single filter object, all specified conditions are AND'd together. - **Balance types**: Include any combination of `PREPAID_COMMIT`, `POSTPAID_COMMIT`, and `CREDIT` (e.g., `["PREPAID_COMMIT", "CREDIT"]` to exclude postpaid commits). If not specified, all balance types are included. - **Specific IDs**: Target exact commit or credit IDs for precise balance queries - **Custom fields**: Filter by custom field key-value pairs; when multiple pairs are provided, commits must match all of them **Example**: To get the balance of all free-trial credits OR all signup-promotion commits, you'd pass two filter objects — one filtering for CREDIT with custom field campaign: free-trial, and another filtering for PREPAID_COMMIT with custom field campaign: signup-promotion. ### Usage guidelines: - **Balance ledger details**: Use the [listBalances](https://docs.metronome.com/api-reference/credits-and-commits/list-balances) endpoint instead to understand detailed ledger drawdowns for each individual balance - **Draft invoice handling**: Use `invoice_inclusion_mode` to control whether pending draft invoice deductions are included (`FINALIZED_AND_DRAFT`, the default) or excluded (`FINALIZED`) from the balance calculation - **Account hierarchies**: When querying a child customer, shared commits from parent contracts are not included — query the parent customer directly to see shared commit balances - **Negative balances**: Manual ledger entries can cause negative segment balances; these are treated as zero when calculating the net balance - **Credit types**: If `credit_type_id` is not specified, the balance defaults to USD (cents) # List balances Source: https://docs.metronome.com/api-reference/credits-and-commits/list-balances /openapi.json post /v1/contracts/customerBalances/list Retrieve a comprehensive view of all available balances (commits and credits) for a customer. This endpoint provides real-time visibility into prepaid funds, postpaid commitments, promotional credits, and other balance types that can offset usage charges, helping you build transparent billing experiences. ### Use this endpoint to: - Display current available balances in customer dashboards - Verify available funds before approving high-usage operations - Generate balance reports for finance teams - Filter balances by contract or date ranges ### Key response fields: An array of balance objects (all credits and commits) containing: - Balance details: Current available amount for each commit or credit - Metadata: Product associations, priorities, applicable date ranges - Optional ledger entries: Detailed transaction history (if `include_ledgers=true`) - Balance calculations: Including pending transactions and future-dated entries - Custom fields: Any additional metadata attached to balances ### Usage guidelines: - Use the [getNetBalance](https://docs.metronome.com/api-reference/credits-and-commits/get-the-net-balance-of-a-customer) endpoint to retrieve a single combined current balance - Date filtering: Use `effective_before` to include only balances with access before a specific date (exclusive) - Set `include_balance=true` for calculated balance amounts on each commit or credit - Set `include_ledgers=true` for full transaction history - Set `include_contract_balances = true` to see contract level balances - Balance logic: Reflects currently accessible amounts, excluding expired/future segments - Manual adjustments: Includes all manual ledger entries, even future-dated ones # List commits Source: https://docs.metronome.com/api-reference/credits-and-commits/list-commits /openapi.json post /v1/contracts/customerCommits/list Retrieve all commit agreements for a customer, including both prepaid and postpaid commitments. This endpoint provides comprehensive visibility into contractual spending obligations, enabling you to track commitment utilization and manage customer contracts effectively. ### Use this endpoint to: - Display commitment balances and utilization in customer dashboards - Track prepaid commitment drawdown and remaining balances - Monitor postpaid commitment progress toward minimum thresholds - Build commitment tracking and forecasting tools - Show commitment history with optional ledger details - Manage rollover balances between contract periods ### Key response fields: An array of Commit objects containing: - Commit type: PREPAID (pay upfront) or POSTPAID (pay at true-up) - Rate type: COMMIT_RATE (discounted) or LIST_RATE (standard pricing) - Access schedule: When commitment funds become available - Invoice schedule: When the customer is billed - Product targeting: Which product(s) usage is eligible to draw from this commit - Optional ledger entries: Transaction history (if `include_ledgers=true`) - Balance information: Current available amount (if `include_balance=true`) - Rollover settings: Fraction of unused amount that carries forward ### Usage guidelines: - Pagination: Results limited to 25 commits per page; use 'next_page' for more - Date filtering options: - `covering_date`: Commits active on a specific date - `starting_at`: Commits with access on/after a date - `effective_before`: Commits with access before a date (exclusive) - Scope options: - `include_contract_commits`: Include contract-level commits (not just customer-level) - `include_archived`: Include archived commits and commits from archived contracts - Performance considerations: - include_ledgers: Adds detailed transaction history (slower) - include_balance: Adds current balance calculation (slower) - Optional filtering: Use commit_id to retrieve a specific commit # List credits Source: https://docs.metronome.com/api-reference/credits-and-commits/list-credits /openapi.json post /v1/contracts/customerCredits/list Retrieve a detailed list of all credits available to a customer, including promotional credits and contract-specific credits. This endpoint provides comprehensive visibility into credit balances, access schedules, and usage rules, enabling you to build credit management interfaces and track available funding. ### Use this endpoint to: - Display all available credits in customer billing dashboards - Show credit balances and expiration dates - Track credit usage history with optional ledger details - Build credit management and reporting tools - Monitor promotional credit utilization • Support customer inquiries about available credits ### Key response fields: An array of Credit objects containing: - Credit details: Name, priority, and which applicable products/tags it applies to - Product ID: The `product_id` of the credit. This is for external mapping into your quote-to-cash stack, not the product it applies to. - Access schedule: When credits become available and expire - Optional ledger entries: Transaction history (if `include_ledgers=true`) - Balance information: Current available amount (if `include_balance=true`) - Metadata: Custom fields and usage specifiers ### Usage guidelines: - Pagination: Results limited to 25 commits per page; use next_page for more - Date filtering options: - `covering_date`: Credits active on a specific date - `starting_at`: Credits with access on/after a date - `effective_before`: Credits with access before a date (exclusive) - Scope options: - `include_contract_credits`: Include contract-level credits (not just customer-level) - `include_archived`: Include archived credits and credits from archived contracts - Performance considerations: - `include_ledgers`: Adds detailed transaction history (slower) - `include_balance`: Adds current balance calculation (slower) - Optional filtering: Use credit_id to retrieve a specific commit # List seat balances Source: https://docs.metronome.com/api-reference/credits-and-commits/list-seat-balances /openapi.json post /v1/contracts/seatBalances/list Retrieve detailed balance for seat-based credits and commits from the contract's subscriptions, broken down by individual seats. ### Use this endpoint to: - Display per-seat balance information in customer dashboards - Filter balance data by subscription or specific seats ### Key response fields: An array of seat balance objects containing: - Seat id - Balance: current total balance across all commits and credits ### Usage guidelines: - Date filtering: use `covering_date` OR `starting_at`/`ending_before` to filter balance data by time range - Set `include_credits_and_commits=true` for detailed commits and credits breakdown per seat - Set `include_ledgers=true` for detailed transaction history per commit/credit per seat # Release external payment gate threshold commit Source: https://docs.metronome.com/api-reference/credits-and-commits/release-external-payment-gate-threshold-commit /openapi.json post /v1/contracts/commits/threshold-billing/release If using threshold billing with an external payment gateway, Metronome does not facilitate the payment gating process on behalf of the client. As a result, clients must facilitate the transaction themselves. This end-point is used to either release or cancel the commit pending on the outcome of the external payment attempt. To release the commit, you must pass the `workflow_id` provided in the `payment_gate.external_initiate` webhook. ### Use this endpoint to: Facilitate payment gating workflows for threshold billing if using a payment gateway Metronome does not support today. ### Usage guidelines: Ensure that you are set up to consume the `payment_gate.external_initiate` webhook and save the `workflow_id`. # Update the commit end date Source: https://docs.metronome.com/api-reference/credits-and-commits/update-the-commit-end-date /openapi.json post /v1/contracts/customerCommits/updateEndDate Shortens the end date of a prepaid commit to terminate it earlier than originally scheduled. Use this endpoint when you need to cancel or reduce the duration of an existing prepaid commit. Only works with prepaid commit types and can only move the end date forward (earlier), not extend it. ### Usage guidelines: To extend commit end dates or make other comprehensive edits, use the 'edit commit' endpoint instead. # Update the credit end date Source: https://docs.metronome.com/api-reference/credits-and-commits/update-the-credit-end-date /openapi.json post /v1/contracts/customerCredits/updateEndDate Shortens the end date of an existing customer credit to terminate it earlier than originally scheduled. Only allows moving end dates forward (earlier), not extending them. Note: To extend credit end dates or make comprehensive edits, use the 'edit credit' endpoint instead. # Custom fields Source: https://docs.metronome.com/api-reference/custom-fields Custom fields are properties that you can add to Metronome objects to store metadata like foreign keys or other descriptors. This metadata can get transferred to or accessed by other systems to contextualize Metronome data and power business processes. For example, to service workflows like [revenue recognition](/guides/reporting-insights/financial-reporting/revenue-recognition-examples), [reconciliation](/guides/reporting-insights/financial-reporting/reconcile-data), and [invoicing in Stripe](/integrations/invoice-integrations/stripe), custom fields help Metronome know the relationship between entities in the platform and third-party systems. ## How custom fields work​ You can add custom fields to most Metronome entities: customer, product, contract, commit, credit, scheduled charge, rate card, and alert. These fields are persisted across the platform and can be fetched in the UI, API, and data export wherever the object appears. When deciding when to create custom fields and where to put them, it’s important to think through the relationship of entities between a given external system and Metronome. For example, to model a NetSuite ERP integration in Metronome, you want to identify what the counterpart is for each object that you want to sync. Frequently, clients sync Metronome invoices to NetSuite and attach the invoices to the related NetSuite customer ID. To store the relationship between them, create a custom field called `netsuite_customer_id` on the Metronome customer object. This field enables a user to query the customer object and determine the foreign key mapping between the two systems. The next example walks through how to associate a line item to a product ID (or SKU) in Stripe by adding a custom field called `stripe_product_id` to the Metronome product. ## Create a custom field​ You can create a custom field using the [Metronome app](https://app.metronome.com/) or API. To create a custom field on a product in the Metronome app: 1. Click **Developer**. 2. Within Developer, click the **Custom fields** tab. 3. Within custom fields, click **Add new field key**. 4. In the resulting modal, select **Product (Contracts)** for entity, enter **stripe\_product\_id** for the **Key** , and turn on the **Unique values required**. 5. Click **Save**. **CAUTION** Enforcing unique values limits the ability to set the same value across multiple objects. Use this to map foreign entities that have a one-to-one relationship with a Metronome object. Uniqueness is enforced even when an object is archived. To resolve a duplicate issue with an archived object, reset the value of the field. To create a custom field with the API, make a POST request to `/customFields/addKey`. The endpoint takes three parameters, all required: * `entity` * `key` * `enforce_uniqueness` ```bash theme={null} curl https://api.metronome.com/v1/customFields/addKey \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "entity": "contract_product", "key": "stripe_product_id", "enforce_uniqueness": true }' ``` ## Set a custom field value​ Once you've defined a custom field on an entity, set values for that field on individual entity instances using the [Metronome app](https://app.metronome.com/) or API. To set a custom field value in the Metronome app: 1. Go to the the **Contract Pricing** page and find the product on the **Product List**. 2. Click on the product record to open the drawer containing the product metadata. 3. Click the overflow button in the top right corner of the drawer and click **Manage custom fields**. 4. Within customer settings, click **Custom fields** —> **Manage**. 5. Within the custom fields page, click **Set custom field**. 6. In the resulting modal, select the field name and provide the field value. 7. Click **Save**. To set a custom field value with the API, make a POST request to `/customFields/setValues`. The endpoint takes three parameters, all required: * `entity` * `entity_id` * `custom_fields` The `custom_fields` parameter accepts an array of key-value pairs, allowing you to set multiple custom field values—on a single entity instance—in one API call. This request updates a specific product, adding the corresponding `stripe_product_id` value: ```bash theme={null} curl https://api.metronome.com/v1/customFields/setValues \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "entity": "contract_product", "entity_id": "76e57c3a-064f-49ad-8740-2bff58f2f808", "custom_fields": { "stripe_product_id": "prod_KyVnHhSBWl7eY2bl" } }' ``` Alternatively, you can set a custom field value on the creation of an object. For example, to set a custom field value on the contract object, you could do this within the POST request to the `/createContract` endpoint. ## Fetch a custom field value​ Once you set a custom field value on an object instance (like a product), the value gets returned when you request that object, including in the Metronome app, API calls, and data exports. As an example, consider the invoice response. Given that products in Metronome map to line items on invoices, the `stripe_product_id` custom field propagates to its associated line item. This mapping enables Metronome to link line items to Stripe products when creating invoices in Stripe. Here’s an example invoice payload: ```json theme={null} { "data": { "id": "09abf41e-2e68-622f-93bc-ce8ef21215de", "issued_at": "2024-09-02T00:00:00+00:00", "start_timestamp": "2024-08-01T00:00:00+00:00", "end_timestamp": "2024-09-01T00:00:00+00:00", "customer_id": "195826717-122e-5150-a96e-ab7ef9744e9c", "customer_custom_fields": {}, "type": "USAGE", "credit_type": { "id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "name": "USD (cents)" }, "status": "DRAFT", "total": 22000, "external_invoice": null, "contract_id": "ccffadcf-5e3b-407d-8c5e-3f678508bfd1", "contract_custom_fields": {}, "line_items": [ { "product_id": "d3d10cd4-e234-4265-91c1-a95f09e6a69c", "product_type": "UsageProductListItem", "product_custom_fields": { "stripe_product_id": "prod_KyVnHhSBWl7eY2bl" }, "name": "Usage Product", "total": 22000, "credit_type": { "id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "name": "USD (cents)" }, "starting_at": "2024-08-01T00:00:00+00:00", "ending_before": "2024-09-01T00:00:00+00:00", "unit_price": 110, "quantity": 200 }, ... ] } } ``` # Create a custom field key Source: https://docs.metronome.com/api-reference/custom-fields/create-a-custom-field-key /openapi.json post /v1/customFields/addKey Creates a new custom field key for a given entity (e.g. billable metric, contract, alert). Custom fields are properties that you can add to Metronome objects to store metadata like foreign keys or other descriptors. This metadata can get transferred to or accessed by other systems to contextualize Metronome data and power business processes. For example, to service workflows like revenue recognition, reconciliation, and invoicing, custom fields help Metronome know the relationship between entities in the platform and third-party systems. ### Use this endpoint to: - Create a new custom field key for Customer objects in Metronome. You can then use the Set Custom Field Values endpoint to set the value of this key for a specific customer. - Specify whether the key should enforce uniqueness. If the key is set to enforce uniqueness and you attempt to set a custom field value for the key that already exists, it will fail. ### Usage guidelines: - Custom fields set on commits, credits, and contracts can be used to scope alert evaluation. For example, you can create a spend threshold alert that only considers spend associated with contracts with custom field key `contract_type` and value `paygo` - Custom fields set on products can be used in the Stripe integration to set metadata on invoices. - Custom fields for customers, contracts, invoices, products, commits, scheduled charges, and subscriptions are passed down to the invoice. # Delete a custom field key Source: https://docs.metronome.com/api-reference/custom-fields/delete-a-custom-field-key /openapi.json post /v1/customFields/removeKey Removes a custom field key from the allowlist for a specific entity type, preventing future use of that key across all instances of the entity. Existing values for this key on entity instances will no longer be accessible once the key is removed. # Delete custom fields Source: https://docs.metronome.com/api-reference/custom-fields/delete-custom-fields /openapi.json post /v1/customFields/deleteValues Remove specific custom field values from a Metronome entity instance by specifying the field keys to delete. Use this endpoint to clean up unwanted custom field data while preserving other fields on the same entity. Requires the entity type, entity ID, and array of keys to remove. # List custom field keys Source: https://docs.metronome.com/api-reference/custom-fields/list-custom-field-keys /openapi.json post /v1/customFields/listKeys Retrieve all your active custom field keys, with optional filtering by entity type (customer, contract, product, etc.). Use this endpoint to discover what custom field keys are available before setting values on entities or to audit your custom field configuration across different entity types. # Set custom field values Source: https://docs.metronome.com/api-reference/custom-fields/set-custom-field-values /openapi.json post /v1/customFields/setValues Sets custom field values on a specific Metronome entity instance. Overwrites existing values for matching keys while preserving other fields. All updates are transactional—either all values are set or none are. Custom field values are limited to 200 characters each. # Archive a customer Source: https://docs.metronome.com/api-reference/customers/archive-a-customer /openapi.json post /v1/customers/archive Use this endpoint to archive a customer while preserving auditability. Archiving a customer will automatically archive all contracts as of the current date and void all corresponding invoices. Use this endpoint if a customer is onboarded by mistake. ### Usage guidelines: - Once a customer is archived, it cannot be unarchived. - Archived customers can still be viewed through the API or the UI for audit purposes. - Ingest aliases remain idempotent for archived customers. In order to reuse an ingest alias, first remove the ingest alias from the customer prior to archiving. - Any notifications associated with the customer will no longer be triggered. # Archive billing provider configurations for a customer Source: https://docs.metronome.com/api-reference/customers/archive-billing-provider-configurations-for-a-customer /openapi.json post /v1/archiveCustomerBillingProviderConfigurations Deprecate an existing billing configuration for a customer to handle churn or billing and collection preference changes. Archiving a billing configuration takes effect immediately. If there are active contracts using the configuration, Metronome will archive the configuration on the contract and immediately stop metering to downstream systems. ### Use this endpoint to: - Remove billing provider customer data and configurations when no longer needed - Clean up test or deprecated billing provider configurations - Free up uniqueness keys for reuse with new billing provider configurations - Disable threshold recharge configurations associated with archived billing providers ### Key response fields: A successful response returns: - `success`: Boolean indicating the operation completed successfully - `error`: Null on success, error message on failure ### Usage guidelines: - Archiving a contract configuration during a grace period will result in the invoice not being sent to the customer - Automatically disables both spend-based and credit-based threshold recharge configurations for contracts using the archived billing provider - You can archive multiple configurations for a single customer in a single request, but any validation failures for an individual configuration will prevent the entire operation from succeeding # Create a customer Source: https://docs.metronome.com/api-reference/customers/create-a-customer /openapi.json post /v1/customers Create a new customer in Metronome and optionally the billing configuration (recommended) which dictates where invoices for the customer will be sent or where payment will be collected. ### Use this endpoint to: Execute your customer provisioning workflows for either PLG motions, where customers originate in your platform, or SLG motions, where customers originate in your sales system. ### Key response fields: This end-point returns the `customer_id` created by the request. This id can be used to fetch relevant billing configurations and create contracts. ### Example workflow: - Generally, Metronome recommends first creating the customer in the downstream payment / ERP system when payment method is collected and then creating the customer in Metronome using the response (i.e. `customer_id`) from the downstream system. If you do not create a billing configuration on customer creation, you can add it later. - Once a customer is created, you can then create a contract for the customer. In the contract creation process, you will need to add the customer billing configuration to the contract to ensure Metronome invoices the customer correctly. This is because a customer can have multiple configurations. - As part of the customer creation process, set the ingest alias for the customer which will ensure usage is accurately mapped to the customer. Ingest aliases can be added or changed after the creation process as well. ### Usage guidelines: For details on different billing configurations for different systems, review the `/setCustomerBillingConfiguration` end-point. # Create or update customer ingest aliases Source: https://docs.metronome.com/api-reference/customers/create-or-update-customer-ingest-aliases /openapi.json post /v1/customers/{customer_id}/setIngestAliases Sets the ingest aliases for a customer. Use this endpoint to associate a Metronome customer with an internal ID for easier tracking between systems. Ingest aliases can be used in the `customer_id` field when sending usage events to Metronome. ### Usage guidelines: - This call is idempotent and fully replaces the set of ingest aliases for the given customer. - Switching an ingest alias from one customer to another will associate all corresponding usage to the new customer. - Use multiple ingest aliases to model child organizations within a single Metronome customer. # Fetch billing provider configurations for a customer Source: https://docs.metronome.com/api-reference/customers/fetch-billing-provider-configurations-for-a-customer /openapi.json post /v1/getCustomerBillingProviderConfigurations Returns all billing configurations previously set for the customer. Use during the contract provisioning process to fetch the `billing_provider_configuration_id` needed to set the contract billing configuration. # Get a customer Source: https://docs.metronome.com/api-reference/customers/get-a-customer /openapi.json get /v1/customers/{customer_id} Get detailed information for a specific customer by their Metronome ID. Returns customer profile data including name, creation date, ingest aliases, configuration settings, and custom fields. Use this endpoint to fetch complete customer details for billing operations or account management. Note: If searching for a customer billing configuration, use the `/getCustomerBillingConfigurations` endpoint. # Get an embeddable customer dashboard Source: https://docs.metronome.com/api-reference/customers/get-an-embeddable-customer-dashboard /openapi.json post /v1/dashboards/getEmbeddableUrl Generate secure, embeddable dashboard URLs that allow you to seamlessly integrate Metronome's billing visualizations directly into your application. This endpoint creates authenticated iframe-ready URLs for customer-specific dashboards, providing a white-labeled billing experience without building custom UI. ### Use this endpoint to: - Embed billing dashboards directly in your customer portal or admin interface - Provide self-service access to invoices, usage data, and credit balances - Build white-labeled billing experiences with minimal development effort ### Key response fields: - A secure, time-limited URL that can be embedded in an iframe - The URL includes authentication tokens and configuration parameters - URLs are customer-specific and respect your security settings ### Usage guidelines: - Dashboard types: Choose from `invoices`, `usage`, or `commits_and_credits` - Customization options: - `dashboard_options`: Configure dashboard behavior. Supported for the invoices dashboard only. Available keys include: `show_zero_usage_line_items` ("true"/"false"), `contract_id` (UUID, filters invoices by contract), `invoice_type` ("USAGE" or "SCHEDULED", filters by invoice type), and `invoice_status_filter` ("VOID", "FINALIZED", "DRAFT", "FINALIZED_AND_DRAFT", or "ALL") - `color_overrides`: Match your brand's color palette - Iframe implementation: Embed the returned URL directly in an iframe element - Responsive design: Dashboards automatically adapt to container dimensions # List customers Source: https://docs.metronome.com/api-reference/customers/list-customers /openapi.json get /v1/customers Gets a paginated list of all customers in your Metronome account. Use this endpoint to browse your customer base, implement customer search functionality, or sync customer data with external systems. Returns customer details including IDs, names, and configuration settings. Supports filtering and pagination parameters for efficient data retrieval. # Set billing provider configurations for a customer Source: https://docs.metronome.com/api-reference/customers/set-billing-provider-configurations-for-a-customer /openapi.json post /v1/setCustomerBillingProviderConfigurations Create a billing configuration for a customer. Once created, these configurations are available to associate to a contract and dictates which downstream system to collect payment in or send the invoice to. You can create multiple configurations per customer. The configuration formats are distinct for each downstream provider. ### Use this endpoint to: - Add the initial configuration to an existing customer. Once created, the billing configuration can then be associated to the customer's contract. - Add a new configuration to an existing customer. This might be used as part of an upgrade or downgrade workflow where the customer was previously billed through system A (e.g. Stripe) but will now be billed through system B (e.g. AWS). Once created, the new configuration can then be associated to the customer's contract. - Multiple configurations can be added per destination. For example, you can create two Stripe billing configurations for a Metronome customer that each have a distinct `collection_method`. ### Delivery method options: - `direct_to_billing_provider`: Use when Metronome should send invoices directly to the billing provider's API (e.g., Stripe, NetSuite). This is the most common method for automated billing workflows. - `tackle`: Use specifically for AWS Marketplace transactions that require Tackle's co-selling platform for partner attribution and commission tracking. - `aws_sqs`: Use when you want invoice data delivered to an AWS SQS queue for custom processing before sending to your billing system. - `aws_sns`: Use when you want invoice notifications published to an AWS SNS topic for event-driven billing workflows. ### Key response fields: The id for the customer billing configuration. This id can be used to associate the billing configuration to a contract. ### Usage guidelines: Must use the `delivery_method_id` if you have multiple Stripe accounts connected to Metronome. # Update a customer configuration Source: https://docs.metronome.com/api-reference/customers/update-a-customer-configuration /openapi.json post /v1/customers/{customer_id}/updateConfig Update configuration settings for a specific customer, such as external system integrations (e.g., Salesforce account ID) and other customer-specific billing parameters. Use this endpoint to modify customer configurations without affecting core customer data like name or ingest aliases. # Update a customer name Source: https://docs.metronome.com/api-reference/customers/update-a-customer-name /openapi.json post /v1/customers/{customer_id}/setName Updates the display name for a customer record. Use this to correct customer names, update business names after rebranding, or maintain accurate customer information for invoicing and reporting. Returns the updated customer object with the new name applied immediately across all billing documents and interfaces. # API idempotency Source: https://docs.metronome.com/api-reference/idempotency This page describes how Metronome supports idempotency so you can safely retry requests without creating duplicate data. Idempotency ensures operations like creating customers or ingesting usage events succeed exactly once, even when requests are retried due to network issues, timeouts, or client logic. Metronome provides built-in idempotency mechanisms so you can safely retry requests without introducing extraneous data. ## How Metronome supports idempotency Metronome uses different idempotency mechanisms depending on the type of data: | Method | Where used | Scope | Conflict behavior | Retention | | ---------------------------- | ------------------------------------ | ---------------------------- | -------------------------------------------------------- | ------------------------------------------ | | **Transaction ID** | Event ingestion (`/ingest`, Segment) | Usage events | Ignores subsequent events with the same ID | 34 days | | **Ingest alias** | Customer writes (create or update) | Customers | Returns `409 Conflict` if ingest alias is already in use | Until released | | **`uniqueness_key`** | Resource creation | Select resources (see below) | Returns `409 Conflict` | Until released (only available for Alerts) | | **`Idempotency-Key` header** | POST API requests | Request cache | Returns `409 Conflict` if parameters differ | ≥ 24 hours | ## Event ingestion [Usage events](/guides/get-started/core-concepts/send-usage-events) stream to Metronome at high scale. To prevent duplicates, Metronome uses the `transaction_id` field as an idempotency key. Once a usage event has been accepted with a given transaction ID, Metronome ignores subsequent events with the same transaction ID within the next 34 days. This allows you to safely retry sending events without risk of duplication. ## Ingest aliases [Ingest aliases](/guides/get-started/core-concepts/provision-customer#understand-ingest-aliases%E2%80%8B) map your internal customer identifiers to a Metronome customer ID. When you send usage keyed on an ingest alias, Metronome automatically associates it with the correct customer. Ingest aliases are also naturally idempotent, preventing the creation of duplicate customer entities or conflicting records. **MOVING INGEST ALIASES** Due to the idempotent nature of ingest aliases, you can move an ingest alias between customers only if you first remove it from the original customer. This rule applies to both archived and active customers. ## API requests Metronome supports two methods of ensuring idempotency through the REST API: * Using uniqueness keys (on select endpoints) * Using the Idempotency-Key header ### Uniqueness keys Metronome supports idempotency for commonly created resources in Metronome by accepting a `uniqueness_key` field in the request payload. This uniqueness key is stored as part of the resource in Metronome, and Metronome ensures that no resources can share the same uniqueness key. If you attempt to create a resource with a uniqueness key already in use, you receive an HTTP `409 Conflict` error with message *“This uniqueness key has already been used.”* Examples of resources with uniqueness keys: * [Contract](/api-reference/contracts/create-a-contract) * [Alert](/api-reference/alerts/create-an-alert) * Customer-level commits and credits * Contract edits \[coming soon] ### Idempotency-Key header Metronome recommends using an `Idempotency-Key` header for endpoints that don’t include a dedicated uniqueness key. Metronome supports sending an `Idempotency-Key` header for all POST endpoints. If the `Idempotency-Key` header is provided and the request begins executing (it passes validation and doesn't conflict with another concurrent request), the results of the API call are persisted, and the same results returned. **Behavior:** * Keys must be unique per request * Retrying with the same key and identical parameters returns the original result. * Retrying with the same key but different parameters returns **HTTP `409 Conflict`**. * Metronome retains idempotency keys for at least 24 hours. * Idempotency applies even if a request returns an HTTP 500 error, meaning Metronome will cache and return the error **Understand idempotency with errors**: When a request with `Idempotency-Key` header returns an error, Metronome caches the error and returns it for subsequent retries with the same idempotency key. **This behavior follows industry best practices**—when an operation fails midway, retries without manual review can make the situation worse. In these situations, Metronome caches and returns the error to ensure you see the failure consistently, investigate the state of the system, and decide whether to retry or resolve manually. ## Best practices * **Generate deterministic keys for resource-based idempotency**: Derive keys from business logic (for example, hash of external ID and operation type) so retries always reuse the same key. * **Use random keys when appropriate**: Generate UUIDs if you don’t need deterministic keys (e.g., `Idempotency-Key` header). * **Match retries to key lifetime**: * Usage events: retry within 34 days. * REST API writes: retry within 24 hours. * **Prefer uniqueness keys when available**: Use `uniqueness_key` for resource creation like contracts instead of the `Idempotency-Key` header. * **Implement safe retries**: Always retry with exponential backoff and reuse the same key. # API Reference Source: https://docs.metronome.com/api-reference/introduction Metronome powers your billing to ensure accurate invoices and enable easy pricing changes as you grow. Our APIs support idempotency, pagination, and customer fields to provide robust flexibility and reliability at any scale. To get started, read our [API Quickstart](/api-reference/api-quickstart), learn more about [How Metronome Works](/guides/get-started/how-metronome-works), or check out our SDKs: # Endpoints Send usage events from your application. Convert raw usage events into invoice quantities. Define line items on an invoice. Set your base prices. Represent your customer relationships. Define invoice behavior for a given customer. Reusable, time-relative sets of contract terms. Modify invoice amounts. A set of charges for a single billing cycle. Power workflows based on state from Metronome. # Get an invoice Source: https://docs.metronome.com/api-reference/invoices/get-an-invoice /openapi.json get /v1/customers/{customer_id}/invoices/{invoice_id} Retrieve detailed information for a specific invoice by its unique identifier. This endpoint returns comprehensive invoice data including line items, applied credits, totals, and billing period details for both finalized and draft invoices. ### Use this endpoint to: - Display historical invoice details in customer-facing dashboards or billing portals. - Retrieve current month draft invoices to show customers their month-to-date spend. - Access finalized invoices for historical billing records and payment reconciliation. - Validate customer pricing and credit applications for customer support queries. ### Key response fields: Invoice status (DRAFT, FINALIZED, VOID) Billing period start and end dates Total amount and amount due after credits Detailed line items broken down by: - Customer and contract information - Invoice line item type - Product/service name and ID - Quantity consumed - Unit and total price - Time period for usage-based charges - Applied credits or prepaid commitments ### Usage guidelines: - Draft invoices update in real-time as usage is reported and may change before finalization - The response includes both usage-based line items (e.g., API calls, data processed) and scheduled charges (e.g., monthly subscriptions, commitment fees) - Credit and commitment applications are shown as separate line items with negative amounts - For voided invoices, the response will indicate VOID status but retain all original line item details # Get an invoice PDF Source: https://docs.metronome.com/api-reference/invoices/get-an-invoice-pdf /openapi.json get /v1/customers/{customer_id}/invoices/{invoice_id}/pdf Retrieve a PDF version of a specific invoice by its unique identifier. This endpoint generates a professionally formatted invoice document suitable for sharing with customers, accounting teams, or for record-keeping purposes. ### Use this endpoint to: - Provide customers with downloadable or emailable copies of their invoices - Support accounting and finance teams with official billing documents - Maintain accurate records of billing transactions for audits and compliance ### Key response details: - The response is a binary PDF file representing the full invoice - The PDF includes all standard invoice information such as line items, totals, billing period, and customer details - The document is formatted for clarity and professionalism, suitable for official use ### Usage guidelines: - Ensure the `invoice_id` corresponds to an existing invoice for the specified `customer_id` - The PDF is generated on-demand; frequent requests for the same invoice may impact performance - Use appropriate headers to handle the binary response in your application (e.g., setting `Content-Type: application/pdf`) # List invoice breakdowns Source: https://docs.metronome.com/api-reference/invoices/list-invoice-breakdowns /openapi.json get /v1/customers/{customer_id}/invoices/breakdowns Retrieve granular time-series breakdowns of invoice data at hourly or daily intervals. This endpoint transforms standard invoices into detailed timelines, enabling you to track usage patterns, identify consumption spikes, and provide customers with transparency into their billing details throughout the billing period. ### Use this endpoint to: - Build usage analytics dashboards showing daily or hourly consumption trends - Identify peak usage periods for capacity planning and cost optimization - Generate detailed billing reports for finance teams and customer success - Troubleshoot billing disputes by examining usage patterns at specific times - Power real-time cost monitoring and alerting systems ### Key response fields: An array of BreakdownInvoice objects, each containing: - All standard invoice fields (ID, customer, commit, line items, totals, status) - Line items with quantities and costs for that specific period - `breakdown_start_timestamp`: Start of the specific time window - `breakdown_end_timestamp`: End of the specific time window - `next_page`: Pagination cursor for large result sets ### Usage guidelines: - Time granularity: Set `window_size` to hour or day based on your analysis needs - Response limits: Daily breakdowns return up to 35 days; hourly breakdowns return up to 24 hours per request - Date filtering: Use `starting_on` and `ending_before` to focus on specific periods - Performance: For large date ranges, use pagination to retrieve all data efficiently - Backdated usage: If usage events arrive after invoice finalization, breakdowns will reflect the updated usage - Zero quantity filtering: Use `skip_zero_qty_line_items=true` to exclude periods with no usage # List invoices Source: https://docs.metronome.com/api-reference/invoices/list-invoices /openapi.json get /v1/customers/{customer_id}/invoices Retrieves a paginated list of invoices for a specific customer, with flexible filtering options to narrow results by status, date range, credit type, and more. This endpoint provides a comprehensive view of a customer's billing history and current charges, supporting both real-time billing dashboards and historical reporting needs. ### Use this endpoint to: - Display historical invoice details in customer-facing dashboards or billing portals. - Retrieve current month draft invoices to show customers their month-to-date spend. - Access finalized invoices for historical billing records and payment reconciliation. - Validate customer pricing and credit applications for customer support queries. - Generate financial reports by filtering invoices within specific date ranges ### Key response fields: Array of invoice objects containing: - Invoice ID and status (DRAFT, FINALIZED, VOID) - Invoice type (USAGE, SCHEDULED) - Billing period start and end dates - Issue date and due date - Total amount, subtotal, and amount due - Applied credits summary - Contract ID reference - External billing provider status (if integrated with Stripe, etc.) - Pagination metadata `next_page` cursor ### Usage guidelines: - The endpoint returns invoice summaries; use the Get Invoice endpoint for detailed line items - Draft invoices are continuously updated as new usage is reported and will show real-time spend - Results are ordered by creation date descending by default (newest first) - When filtering by date range, the filter applies to the billing period, not the issue date - For customers with many invoices, implement pagination to ensure all results are retrieved External billing provider statuses (like Stripe payment status) are included when applicable - Voided invoices are included in results by default unless filtered out by status # Preview events Source: https://docs.metronome.com/api-reference/invoices/preview-events /openapi.json post /v1/customers/{customer_id}/previewEvents Preview how a set of events will affect a customer's invoices. Generates draft invoices for a customer using their current contract configuration and the provided events. This is useful for testing how new events will affect the customer's invoices before they are actually processed. Customers on contracts with SQL billable metrics are not supported. # Regenerate an invoice Source: https://docs.metronome.com/api-reference/invoices/regenerate-an-invoice /openapi.json post /v1/invoices/regenerate This endpoint regenerates a voided invoice and recalculates the invoice based on up-to-date rates, available balances, and other fees regardless of the billing period. ### Use this endpoint to: Recalculate an invoice with updated rate terms, available balance, and fees to correct billing disputes or discrepancies ### Key response fields: The regenerated invoice id, which is distinct from the previously voided invoice. ### Usage guidelines: If an invoice is attached to a contract with a billing provider on it, the regenerated invoice will be distributed based on the configuration. # API Pagination Source: https://docs.metronome.com/api-reference/pagination Calling any list method that returns multiple results, such as `/customers`, may require pagination: multiple calls to fetch all the results. Metronome provides two URL parameters on all list endpoints for this purpose: * `limit` customizes how many results are returned per page * `next_page` specifies the cursor to use as a starting point to fetch the next set of results When a returned response contains a `next_page` value, more records exist than were returned. Include that `next_page` value in a subsequent query to fetch the next set of results. To fetch every result, repeat this process until `next_page` is null. ```bash theme={null} GET /v1/customers?limit=10 ``` ```json theme={null} { "data": [ { "id": 1 }, { "id": 2 }, // ... ] // The next_page cursor that can be passed in the URL // to get the next set of results. "next_page": "0c34b75b47491b73db66d46737d9a87" } ``` Given the above response, you can provide the `next_page` cursor with the next request. ```bash theme={null} GET /v1/customers?limit=10&next_page=0c34b75b47491b73db66d46737d9a87 ``` ```json theme={null} { "data": [ { "id": 3 } ], // If no next_page value is returned, this is the last page of results. "next_page": null } ``` **BEST PRACTICES FOR LIMIT** To make a quick API call to inspect the response format, set `limit=1`. To load many results with as few API calls as possible, set `limit=50`. For performance reasons, `limit` is capped at `100`. # Use Postman with Metronome Source: https://docs.metronome.com/api-reference/postman [Postman](https://www.postman.com/) is a great way to visually explore the Metronome API without writing code. Before you start, you need to: * Create a [free account with Postman](https://postman.com/) * Request a [Metronome account](https://metronome.com/talk-to-an-expert) * Generate a Metronome [API token](/api-reference/authorization) ## Use the OpenAPI spec​ The [Metronome OpenAPI spec](https://api.metronome.com/v1/docs/openapi) can be [imported directly into Postman](https://learning.postman.com/docs/integrations/available-integrations/working-with-openAPI/). The spec is always up to date. To import the OpenAPI spec: 1. In Postman, go to **File** > **Import**. 2. Select **Link** from the top menu, and enter Metronome's OpenAPI spec link ([https://api.metronome.com/v1/docs/openapi](https://api.metronome.com/v1/docs/openapi)). 3. On the next pane, select **Show advanced settings** and make sure the **Folder organization** is set as **Tags**. Postman OpenAPI import screenshot ### Set up authorization for the Metronome collection​ The Metronome API uses a Bearer Token. To set Auth up in the collection, click on your collection's top-level **Metronome** folder and select **Bearer Token**. Set Auth to bearer token We recommend using a [Postman variable](https://learning.postman.com/docs/sending-requests/variables/) for the token value. To do this, enter `{{api_token}}` in the box below the **Type** dropdown. A window appears referencing an unresolved variable. In that box, click on **Add new variable** , add your Metronome API token as the value, and set the scope to **Collection: Metronome**. Create variable in Postman for API token ### Organize the Metronome collection​ A [Postman Collection](https://www.postman.com/collection/) groups requests together in a folder structure, allowing them to be easily organized. You can [fork](https://learning.postman.com/docs/collaborating-in-postman/version-control-for-collections/) the collection if needed. Forking provides for version control and facilitates collaboration. ## Try it out​ To test the Metronome API using Postman, create a new customer using the **Create customer** request. To do so you must configure the **Create customer** request to use the Bearer Token variable `{{api_token}}`. 1. Navigate to **Customers** > **POST Create customer**. 2. Select **Authorization** , then select **Bearer Token** from the **Type** dropdown. Since we scoped `{{api_token}}` for the entire collection, the **Token** value should automatically be set to `{{api_token}}`. If not, just enter `{{api_token}}` in the **Token** box. 3. Save your changes to the **Create customer** request. Set auth for create customer request Now that auth is set, create a new customer using the below JSON as the body of the request. Navigate to **Customers** > **POST Create customer** , select **Body** from the request options in the panel, then enter the following: ```json theme={null} { "name": "Example-Customer" } ``` The API response is in the format ```json theme={null} { "data": { "id": "d7abd0cd-4ae9-4db7-8676-e986a4ebd8dc", "external_id": "d7abd0cd-4ae9-4db7-8676-e986a4ebd8dc", "name": "Example-Customer" } } ``` Now that the collection is set up, you can continue with the Metronome API. # Build with the Metronome SDKs Source: https://docs.metronome.com/api-reference/sdks Metronome provides powerful software development kits (SDKs) designed to seamlessly integrate Metronome billing APIs into your applications. The SDKs for Python, Go, Ruby, Node.js, and Java offer developers flexible options for implementing Metronome's capabilities across platforms and environments. This page walks through a basic but powerful usage-based billing system in Python, Node, Ruby, or Golang: 1. Install and configure the Metronome SDK. 2. Send usage events to Metronome, laying the foundation for consumption-based billing. 3. Create a billable metric to define how Metronome should aggregate and measure usage. 4. Create a customer in the system and associate them with usage events. 5. Set up pricing and packing for your product. 6. Create a contract for the customer, enabling automatic invoice generation based on their usage. ## SDK features​ Each SDK GitHub repository contains detailed documentation, examples, and resources to help you make the most of Metronome in your applications: * [Python SDK](https://github.com/Metronome-Industries/metronome-python/blob/main/README.md) * [Go SDK](https://github.com/Metronome-Industries/metronome-go/blob/main/README.md) * [Ruby SDK](https://github.com/Metronome-Industries/metronome-ruby/blob/main/README.md) * [Node.js SDK](https://github.com/Metronome-Industries/metronome-node/blob/main/README.md) * [Java SDK](https://github.com/Metronome-Industries/metronome-java/blob/main/README.md) Core SDK features include: * **Strong typing of Metronome endpoints and objects** enhance developer productivity with better autocomplete and IDE support for Metronome objects. * **Pagination support** simplifies the process of retrieving and managing paginated data from Metronome services. * **Automatic retry support** by default retries each request upon failure up to three times. You can configure it to any number of retries. Use this to automatically handle transient errors and network issues without needing to implement retry logic. While this guide covered the fundamentals, Metronome offers much more functionality to model different business models. Check out the SDK repo to see what’s possible. ## 1. Install and configure the SDK​ First install and configure the SDK in your environment: ```bash Python theme={null} pip install --pre metronome-sdk ``` ```bash Node theme={null} npm install @metronome/sdk ``` ```bash Ruby theme={null} gem install metronome-sdk ``` ```bash Go theme={null} go get -u 'github.com/Metronome-Industries/metronome-go' ``` Next, configure the SDK by passing a valid [API key](/api-reference/authorization) as the authorization bearer token. By default, the SDK looks for the API key under the environment variable `METRONOME_BEARER_TOKEN`. In this example, it'll be passed as an argument to the constructor instead. ```python Python theme={null} from metronome import Metronome client = Metronome( # Defaults to os.environ.get("METRONOME_BEARER_TOKEN") if omitted bearer_token="My bearer token", ) ``` ```javascript Node theme={null} import Metronome from '@metronome/sdk' const client = new Metronome({ // Defaults to os.environ.get("METRONOME_BEARER_TOKEN") if omitted bearerToken: "My bearer token", }); ``` ```ruby Ruby theme={null} require "bundler/setup" require "metronome_sdk" metronome = MetronomeSDK::Client.new( bearer_token: "My Bearer Token" # defaults to ENV["METRONOME_BEARER_TOKEN"] ) ``` ```go Go theme={null} package main import ( "context" "github.com/Metronome-Industries/metronome-go" "github.com/Metronome-Industries/metronome-go/option" ) func main() { client := metronome.NewClient( option.WithBearerToken("My bearer token"), // defaults to os.LookupEnv("METRONOME_BEARER_TOKEN") if omitted ) } ``` ## 2. Send usage events​ The usage-based billing model builds upon captured usage data from users on your platform. Metronome accepts usage payloads of all formats through the [/ingest](/api-reference/usage/ingest-events) endpoint. Use the SDK to send data to Metronome: ```python Python theme={null} response = client.v1.usage.ingest( usage=[ { "transaction_id": "9995a70e-a2c5-4904-b96d-70de446f420e", "timestamp": "2024-08-01T00:00:00Z", "customer_id": "team@example.com", "event_type": "language_model", "properties": { "model": "langModel4", "user_id": "johndoe", "tokens": 1000000 } } ] ) ``` ```javascript Node theme={null} async function main() { await client.v1.usage.ingest({ usage: [{ transaction_id: '9995a70e-a2c5-4904-b96d-70de446f420e', timestamp: "2024-08-01T00:00:00.000Z", customer_id: 'team@example.com', event_type: 'language_model', properties: { model: "langModel4", user_id: "johndoe", tokens: 1000000 } }], }); } main(); ``` ```ruby Ruby theme={null} result = metronome.v1.usage.ingest( usage: [ { transaction_id: '9995a70e-a2c5-4904-b96d-70de446f420e', timestamp: "2024-08-01T00:00:00.000Z", customer_id: 'team@example.com', event_type: 'language_model', properties: { model: "langModel4", user_id: "johndoe", tokens: 1000000 } } ] ) puts(result) ``` ```go Go theme={null} err := client.V1.Usage.Ingest(context.TODO(), metronome.UsageIngestParams{ Usage: []metronome.UsageIngestParamsUsage{{ TransactionID: metronome.F("9995a70e-a2c5-4904-b96d-70de446f420e"), Timestamp: metronome.F("2024-08-01T00:00:00Z"), CustomerID: metronome.F("team@example.com"), EventType: metronome.F("language_model"), Properties: metronome.F(map[string]interface{}{ "model": "langModel4", "user_id": "johndoe", "tokens": 1000000, }), }}, }) if err != nil { panic(err.Error()) } ``` The properties used in this example include: * `usage`, allows you to pass in multiple event payloads in a request. Metronome supports passing up to 100 events within a single request. * `transaction_id`, provides Metronome with the unique idempotency key for the event. Metronome deduplicates based on this ID, allowing you to send events potentially many times without worrying about double-charging your customers. * `timestamp`, the time when the event occurred. Send in events with any timestamp up to 34 days in the past. * `customer_id`, the customer ID in Metronome or any other customer identifier you want to define. For example, customer email or internal customer ID within your platform. Later steps show how to define these custom identifiers for your customers in Metronome. * `event_type`, an arbitrary string that you can define within the request. * `properties`, an arbitrary set of data to include within the payload for metering and grouping within Metronome. Success with Metronome depends on the data you provide, so it's important to design [usage events](/guides/events/design-usage-events) well. To view all events sent to Metronome, go to the **Events tab** in the [Metronome app](https://app.metronome.com/). For the event sent in the example, it successfully made it into the Metronome system. But, it hasn’t been matched yet with a metric to start metering or a customer in the system. View an event ## 3. Create a billable metric​ A billable metric describes a per-customer aggregation over a subset of usage events. By configuring a billable metric, you instruct Metronome how to match usage events to products you charge for. Here's an example billable metric configuration that matches against the usage event sent in the previous example: ```python Python theme={null} response = client.v1.billable_metrics.create( name="langModel4", event_type_filter={ "in_values": [ "language_model" ] }, property_filters=[ { "name": "model", "exists": True, "in_values": [ "langModel4" ] }, { "name": "user_id", "exists": True }, { "name": "tokens", "exists": True } ], aggregation_key="tokens", aggregation_type="SUM", group_keys=[ ["user_id"] ] ) billable_metric_id = response.data.id ``` ```javascript Node theme={null} const billableMetricsResponse = await client.v1.billableMetrics.create({ name: "langModel4", event_type_filter: { in_values: [ "language_model" ] }, property_filters: [ { name: "model", exists: true, in_values: [ "langModel4" ] }, { name: "user_id", exists: true }, { name: "tokens", exists: true, } ], aggregation_key: "tokens", aggregation_type: "SUM", group_keys: [ ["user_id"] ] }); const billableMetricId = billableMetricsResponse.data.id; ``` ```ruby Ruby theme={null} response = client.v1.billable_metrics.create( name: "langModel4", event_type_filter: { in_values: [ "language_model" ] }, property_filters: [ { name: "model", exists: true, in_values: [ "langModel4" ] }, { name: "user_id", exists: true }, { name: "tokens", exists: true } ], aggregation_key: "tokens", aggregation_type: "SUM", group_keys: [ ["user_id"] ] ) billable_metric_id = response.data.id ``` ```go Go theme={null} billableMetricResponse, err := client.V1.BillableMetrics.New(context.TODO(), metronome.BillableMetricNewParams{ Name: metronome.F("langModel4"), EventTypeFilter: metronome.F(metronome.EventTypeFilterParam{ InValues: metronome.F([]string{"language_model"}), }), PropertyFilters: metronome.F([]metronome.PropertyFilterParam{ { Name: metronome.F("model"), Exists: metronome.F(true), InValues: metronome.F([]string{ "langModel4", }), }, { Name: metronome.F("user_id"), Exists: metronome.F(true), }, { Name: metronome.F("tokens"), Exists: metronome.F(true), }, }), AggregationKey: metronome.F("tokens"), AggregationType: metronome.F(metronome.BillableMetricNewParamsAggregationTypeSum), }) if err != nil { panic(err.Error()) } billableMetricID := billableMetricResponse.Data.ID ``` The properties used in the code include: * `name`, the name to give your billable metric. * `event_type_filter`, the set of values that matched against the `event_type` field in the usage events. Omit this if you want to match against all event types. * `property_filters`, the set of properties you expect to find on the usage payload. If you mark a property as `exists=True` in the billable metric definition and the property not found on the payload, the billable metric won’t match to the event. * `aggregation_key`, used to define the property with the relevant value to aggregate on. * `aggregation_type`, used to tell Metronome how to aggregate the values specified by the `aggregation_key` as they come into the system. Supported operations are `SUM`, `COUNT`, and `MAX`. * `group_keys`, used to define properties to separate the usage data into different buckets, similar to a `group by` clause in SQL. The example above set `user_id` as a group key, so you can display the invoice separated by the amount of tokens that each user consumed. Billable metric Note that billable metrics only match usage events sent after the billable metric is created. Now that you created the metric, send in another usage event to ensure that it matches as expected: ```python Python theme={null} response = client.v1.usage.ingest( usage=[ { "transaction_id": "7e28f511-d66c-4517-91ef-a92c108e56de", "timestamp": "2024-08-01T00:00:00Z", "customer_id": "team@example.com", "event_type": "language_model", "properties": { "model": "langModel4", "user_id": "johndoe", "tokens": 1000000 } } ] ) ``` ```javascript Node theme={null} await client.v1.usage.ingest({ usage: [ { transaction_id: '7e28f511-d66c-4517-91ef-a92c108e56de', timestamp: "2024-08-01T00:00:00.000Z", customer_id: 'team@example.com', event_type: 'language_model', properties: { model: "langModel4", user_id: "johndoe", tokens: 1000000 } } ] }); ``` ```ruby Ruby theme={null} response = client.v1.usage.ingest( usage: [ { transaction_id: "7e28f511-d66c-4517-91ef-a92c108e56de", timestamp: "2024-08-01T00:00:00Z", customer_id: "team@example.com", event_type: "language_model", properties: { model: "langModel4", user_id: "johndoe", tokens: 1000000 } } ] ) ``` ```go Go theme={null} err := client.V1.Usage.Ingest(context.TODO(), metronome.UsageIngestParams{ Usage: []metronome.UsageIngestParamsUsage{{ TransactionID: metronome.F("7e28f511-d66c-4517-91ef-a92c108e56de"), Timestamp: metronome.F("2024-08-01T00:00:00Z"), CustomerID: metronome.F("team@example.com"), EventType: metronome.F("language_model"), Properties: metronome.F(map[string]interface{}{ "model": "langModel4", "user_id": "johndoe", "tokens": 1000000, }), }}, }) if err != nil { panic(err.Error()) } ``` The new usage event matches the defined billable metric. Billable metric with a usage event ## 4. Create a customer​ Usage events impact billing for customers, so the next step is to create a customer in Metronome. Use the SDK to create a customer, similar to this example: ```python Python theme={null} response = client.v1.customers.create( name="Example Customer", ingest_aliases=[ "team@example.com" ] ) metronome_customer_id = response.data.id ``` ```javascript Node theme={null} const customerResponse = await client.v1.customers.create({ name: "Example Customer", ingest_aliases: [ "team@example.com" ] }); const customerId = customerResponse.data.id; ``` ```ruby Ruby theme={null} response = client.v1.customers.create( name: "Example Customer", ingest_aliases: [ "team@example.com" ] ) metronome_customer_id = response.data.id ``` ```go Go theme={null} customerResponse, err := client.V1.Customers.New(context.TODO(), metronome.CustomerNewParams{ Name: metronome.F("Example Customer"), IngestAliases: metronome.F([]string{ "team@example.com", }), }) if err != nil { panic(err.Error()) } customerID := customerResponse.Data.ID ``` The properties used in this example include: * `name`, the display name for the customer in Metronome. * `ingest_aliases`, a list of identifiers used to match a Metronome customer against a usage event. Ingest aliases are useful if you want to start flowing in usage for customers before they’re created in Metronome. To do this, use the ID from your application’s customer table. New customer In the example, you associated the newly created customer with the ingest alias `team@example.com`, so the previous event gets matched correctly. After you set the customer up for invoicing in the next section, this event contributes to their current invoice. Billable metric for the customer ## 5. Set up pricing and packaging​ Next, set up prices and packaging, defined using products and rate cards. In the example, you want to charge your customer based on their usage of `langModel4` at a rate of \$0.50 per 1 million tokens. The first step is to create a `product` for your billable metric. A product is where you configure the billable metric for presentation on the eventual invoice. It’s also where you can associate the metric with items in external systems, like the Stripe customer ID. Learn about the configuration options for products in the API docs for the [create product](/api-reference/products/create-a-product) endpoint. Create a product associated to the billable metric, similar to this example: ```python Python theme={null} response = client.v1.contracts.products.create( name="Language Model 4 Tokens (millions)", type="USAGE", billable_metric_id=billable_metric_id, # ID from create billable metric response presentation_group_key=["user_id"], quantity_conversion={ "conversion_factor": 1000000, "operation": "divide" } ) product_id = response.data.id ``` ```javascript Node theme={null} const productResponse = await client.v1.contracts.products.create({ name: "Language Model 4 Tokens (millions)", type: "USAGE", billable_metric_id: billableMetricId, // ID from create billable metric response presentation_group_key: ["user_id"], quantity_conversion: { conversion_factor: 1000000, operation: "DIVIDE" } }); const productId = productResponse.data.id; ``` ```ruby Ruby theme={null} response = client.v1.contracts.products.create( name: "Language Model 4 Tokens (millions)", type: "USAGE", billable_metric_id: billable_metric_id, # ID from create billable metric response presentation_group_key: ["user_id"], quantity_conversion: { conversion_factor: 1000000, operation: "divide" } ) product_id = response.data.id ``` ```go Go theme={null} productResponse, err := client.V1.Contracts.Products.New(context.TODO(), metronome.ContractProductNewParams{ Name: metronome.F("Language Model 4 Tokens (millions)"), Type: metronome.F(metronome.ContractProductNewParamsTypeUsage), BillableMetricID: metronome.F(billableMetricId), PresentationGroupKey: metronome.F([]string{ "user_id", }), QuantityConversion: metronome.F(metronome.QuantityConversionParam{ ConversionFactor: metronome.F(1000000.0), Operation: metronome.F(metronome.QuantityConversionOperationDivide), }), }) if err != nil { panic(err.Error()) } productID := productResponse.Data.ID ``` The properties used in this example include: * `name`, the name of the product that appears on the invoice. Often a cleaned presentation of the billable metric name (`Language Model 4 Tokens (millions)` versus `langModel4`). * `type`, determines how a product gets charged. Supported types include `usage`, `fixed`, `composite` (for percentages of other usage products), and `subscription`. * `billable_metric_id`, associates the product presentation with an existing billable metric. * `presentation_group_key`, used to group line items on your invoice by a given property value. * `quantity_conversion`, used to multiply or divide quantities displayed on the final invoice. For example, charge by million tokens (mTok) while sending in usage at the individual token level. Converted billable metric Next, attach a price for the product by adding rates to a rate card. Build a rate card for your new product, similar to this example: ```python Python theme={null} response = client.v1.contracts.rate_cards.create( name="Language Model List Pricing", description="Prices for all language models.", ) rate_card_id = response.data.id response = client.v1.contracts.rate_cards.rates.add( rate_card_id=rate_card_id, product_id=product_id, entitled=True, rate_type="FLAT", price=50, starting_at="2024-01-01T00:00:00.000Z" ) ``` ```javascript Node theme={null} const rateCardResponse = await client.v1.contracts.rateCards.create({ name: "Language Model List Pricing", description: "Prices for all language models." }); const rateCardId = rateCardResponse.data.id; await client.v1.contracts.rateCards.rates.add({ rate_card_id: rateCardId, product_id: productId, entitled: true, rate_type: "FLAT", price: 50, starting_at: "2024-01-01T00:00:00.000Z" }); ``` ```ruby Ruby theme={null} response = client.v1.contracts.rate_cards.create( name: "Language Model List Pricing", description: "Prices for all language models." ) rate_card_id = response.data.id response = client.v1.contracts.rate_cards.rates.add( rate_card_id: rate_card_id, product_id: product_id, entitled: true, rate_type: "FLAT", price: 50, starting_at: "2024-01-01T00:00:00.000Z" ) ``` ```go Go theme={null} rateCardResponse, err := client.V1.Contracts.RateCards.New(context.TODO(), metronome.ContractRateCardNewParams{ Name: metronome.F("Language Model List Pricing"), Description: metronome.F("Prices for all language models."), }) if err != nil { panic(err.Error()) } rateCardID := rateCardResponse.Data.ID startingTime, err := time.Parse(time.RFC3339Nano, "2024-01-01T00:00:00.000Z") if err != nil { panic(err.Error()) } _, err = client.V1.Contracts.RateCards.Rates.Add(context.TODO(), metronome.ContractRateCardRateAddParams{ RateCardID: metronome.F(rateCardID), ProductID: metronome.F(productID), Entitled: metronome.F(true), RateType: metronome.F(metronome.ContractRateCardRateAddParamsRateTypeFlat), Price: metronome.F(50.0), StartingAt: metronome.F(startingTime), }) if err != nil { panic(err.Error()) } ``` The properties used in this example include: * `entitled`, a boolean that indicates whether a rate shows up by default on a customer’s invoice. If `False`, it won’t appear on a customer’s invoice unless overridden at the contract level. * `rate_type`, used to configure how a rate gets applied as usage flows in. Supported values include `FLAT` or `TIERED`. * `price`, the rate itself. For USD, values are in **cents** (for example, `100` = \$1.00). Other currencies use whole units. See [currency denomination](/guides/pricing-packaging/make-pricing-changes/use-currency-custompricingunits#currency-denomination) for details. * `starting_at`, used to set the time when the rate goes into effect. To evolve your rates over time, set `starting_at` and `ending_before` dates to ensure smooth pricing updates. You can use this rate card for all SKUs across your product catalog. ## 6. Create a contract​ To start generating invoices for a customer, put them on a contract. A contract is an object that represents the terms a customer has agreed to pay, generally based on your rate card. At its most simple, a customer can have a basic contract where they pay the predefined list prices; this may cover many of your simple self-serve cases. If you have specific discounts or commits that a customer negotiated, configure these in the contract on top of the base list prices. Add your created customer to a contract, similar to this example that uses the Language Model List Pricing rate card: ```python Python theme={null} response = client.v1.contracts.create( customer_id=metronome_customer_id, rate_card_id=rate_card_id, starting_at="2024-08-01T00:00:00.000Z" ) ``` ```javascript Node theme={null} await client.v1.contracts.create({ customer_id: customerId, rate_card_id: rateCardId, starting_at: "2024-08-01T00:00:00.000Z" }); ``` ```ruby Ruby theme={null} response = client.v1.contracts.create( customer_id: metronome_customer_id, rate_card_id: rate_card_id, starting_at: "2024-08-01T00:00:00.000Z" ) ``` ```go Go theme={null} contractStartingTime, err := time.Parse(time.RFC3339Nano, "2024-09-01T00:00:00.000Z") if err != nil { panic(err.Error()) } contractResponse, err := client.V1.Contracts.New(context.TODO(), metronome.ContractNewParams{ CustomerID: metronome.F(customerID), RateCardID: metronome.F(rateCardID), StartingAt: metronome.F(contractStartingTime), }) if err != nil { panic(err.Error()) } contractID := contractResponse.Data.ID ``` After creating the contract, invoices get generated for all billing periods that occurred after the `starting_at` date. Usage data from the current period is visible to the `DRAFT` invoice. Line items on draft invoices update seconds after Metronome receives usage data. For the new contract from the example, the previously sent usage of 1 million tokens got applied. New contract Next, send in a few more usage events and see it update in real time: ```python Python theme={null} response = client.v1.usage.ingest( usage=[ { "transaction_id": "382a3069-d056-4249-824d-d288b51d7743", "timestamp": "2024-08-15T04:39:20Z", "customer_id": "team@example.com", "event_type": "language_model", "properties": { "model": "langModel4", "user_id": "johndoe", "tokens": 1000000 } }, { "transaction_id": "db64bf17-f13d-4c19-89cc-acaf878a42c6", "timestamp": "2024-08-16T19:11:02Z", "customer_id": "team@example.com", "event_type": "language_model", "properties": { "model": "langModel4", "user_id": "janedoe", "tokens": 5500000 } }, { "transaction_id": "266339fd-2125-4827-afb7-a395a7f0007f", "timestamp": "2024-08-17T12:51:32Z", "customer_id": "team@example.com", "event_type": "language_model", "properties": { "model": "langModel4", "user_id": "johndoe", "tokens": 3000000 } }, ] ) ``` ```javascript Node theme={null} await client.v1.usage.ingest({ usage: [ { transaction_id: '382a3069-d056-4249-824d-d288b51d7743', timestamp: "2024-08-15T04:39:20Z", customer_id: 'team@example.com', event_type: 'language_model', properties: { model: "langModel4", user_id: "johndoe", tokens: 1000000 } }, { transaction_id: 'db64bf17-f13d-4c19-89cc-acaf878a42c6', timestamp: "2024-08-16T19:11:02Z", customer_id: 'team@example.com', event_type: 'language_model', properties: { model: "langModel4", user_id: "janedoe", tokens: 5500000 } }, { transaction_id: '266339fd-2125-4827-afb7-a395a7f0007f', timestamp: "2024-08-17T12:51:32Z", customer_id: 'team@example.com', event_type: 'language_model', properties: { model: "langModel4", user_id: "johndoe", tokens: 3000000 } }, ] }); ``` ```ruby Ruby theme={null} response = client.v1.usage.ingest( usage: [ { transaction_id: "382a3069-d056-4249-824d-d288b51d7743", timestamp: "2024-08-15T04:39:20Z", customer_id: "team@example.com", event_type: "language_model", properties: { model: "langModel4", user_id: "johndoe", tokens: 1000000 } }, { transaction_id: "db64bf17-f13d-4c19-89cc-acaf878a42c6", timestamp: "2024-08-16T19:11:02Z", customer_id: "team@example.com", event_type: "language_model", properties: { model: "langModel4", user_id: "janedoe", tokens: 5500000 } }, { transaction_id: "266339fd-2125-4827-afb7-a395a7f0007f", timestamp: "2024-08-17T12:51:32Z", customer_id: "team@example.com", event_type: "language_model", properties: { model: "langModel4", user_id: "johndoe", tokens: 3000000 } } ] ) ``` ```go Go theme={null} err := client.V1.Usage.Ingest(context.TODO(), metronome.UsageIngestParams{ Usage: []metronome.UsageIngestParamsUsage{ { TransactionID: metronome.F("382a3069-d056-4249-824d-d288b51d7743"), Timestamp: metronome.F("2024-08-15T04:39:20Z"), CustomerID: metronome.F("team@example.com"), EventType: metronome.F("language_model"), Properties: metronome.F(map[string]interface{}{ "model": "langModel4", "user_id": "johndoe", "tokens": 1000000, }), }, { TransactionID: metronome.F("db64bf17-f13d-4c19-89cc-acaf878a42c6"), Timestamp: metronome.F("2024-08-16T19:11:02Z"), CustomerID: metronome.F("team@example.com"), EventType: metronome.F("language_model"), Properties: metronome.F(map[string]interface{}{ "model": "langModel4", "user_id": "janedoe", "tokens": 5500000, }), }, { TransactionID: metronome.F("266339fd-2125-4827-afb7-a395a7f0007f"), Timestamp: metronome.F("2024-08-17T12:51:32Z"), CustomerID: metronome.F("team@example.com"), EventType: metronome.F("language_model"), Properties: metronome.F(map[string]interface{}{ "model": "langModel4", "user_id": "johndoe", "tokens": 3000000, }), }, }, }) if err != nil { panic(err.Error()) } ``` After refreshing the invoice, the values from the three event payloads above applies to the running line item totals. The group keys previously applied let you separate out the invoice presentation by the user ID associated with the usage. Updated contract # API status codes Source: https://docs.metronome.com/api-reference/status-codes This page describes how Metronome uses HTTP status codes to indicate whether an API request succeeded or failed. It helps you interpret and handle different types of errors. Metronome uses standard HTTP status codes: * **2xx** indicates success * **4xx** indicates a client error (e.g., a required parameter was omitted) * **5xx** indicates a Metronome server error Every `4XX` error uses this `application/json` format: ```json theme={null} { "message": "Descriptive error text" } ``` The table lists the most common HTTP status codes returned by the Metronome API, along with a possible solution. | **Code** | **Meaning** | **Description** | **Possible solution** | | -------- | -------------------- | --------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | | 200 | OK | Everything worked as expected | N/A—the request was successful | | 400 | Bad Request | The request was unacceptable, often due to malformed syntax, or a missing or malformed parameter | Ensure request syntax is correct | | 401 | Invalid access token | Requestor is unauthorized or does not have permission for this API call | Ensure API token is valid | | 403 | Forbidden | Requestor does not have access to this resource | Ensure API token is valid | | 404 | Resource not found | The requested resource does not exist | Ensure ID of requested resource is valid | | 409 | Conflict | The request could not be processed due to a conflict with the current state of an existing resource | Ensure that the object doesn't already exist, and if using an [Idempotency-Key header](/api-reference/idempotency), check that it's unique | | 429 | Too Many Requests | Too many requests hit the API too quickly | Check the `X-Metronome-Rate-Limit-Type` header to determine the limit scope (see below), then backoff and try again later | | 5XX | Server Errors | Something went wrong while servicing your request | Retry your request. If using Idempotency-Key header, verify that resource was not partially created and retry using a different key | ## Rate limit headers When a request is rate limited (HTTP 429), the response includes an `X-Metronome-Rate-Limit-Type` header indicating which limit was exceeded: | **Header value** | **Meaning** | | ---------------- | --------------------------------------------------------------------- | | `client` | Your organization's overall rate limit for this endpoint was exceeded | | `customer` | The per-customer rate limit for the targeted customer was exceeded | # Allowlist the Metronome API Source: https://docs.metronome.com/guides/platform-configuration/allowlist Metronome supports IP allowlisting for accessing its APIs. Implementing an allowlist restricts Metronome API access to a specific set of IP addresses, enhancing security by limiting potential entry points for unauthorized access. ## Implement allowlisting​ To implement allowlisting: 1. Retrieve Metronome’s API IP addresses by polling the [getServices](/api-reference/security/get-services) endpoint. 2. Use response IPs to configure your organization’s allowlist in accordance with your security protocols and network security tools. ## Test and automate to ensure access​ You must take action to ensure continued access and security with IP allowlisting. This is due to: * **IP address changes**\ Metronome's IP addresses are subject to change. New IPs appear in the list at least 30 days before they are first used. * **Polling frequency**\ Failure to regularly poll the `getServices` API to update your allowlist may result in losing access to Metronome APIs, as IPs get frequently rotated in and out of service. * **Security layers**\ While IP allowlisting can add an extra layer of security, use it in conjunction with additional security measures like SSO and scoped RBAC roles. For optimal use of IP allowlisting, follow these best practices: * Automate the process of regularly polling the `getServices` API and updating your allowlist * Test your allowlist configuration regularly to ensure continued access to Metronome APIs * Maintain a changelog of updates to your allowlist for auditing purposes **NEED HELP?** If you encounter any issues with IP allowlisting or have questions about implementation, contact us via the [Metronome support portal](https://support.metronome.com/). # Audit logs Source: https://docs.metronome.com/guides/platform-configuration/audit-logs The Metronome audit log tracks actions taken anywhere in the Metronome system (such as the [Metronome app](https://app.metronome.com/) or API). The log records metadata around that action, including who took it, when it occurred, and how the system responded to the action. This provides increased transparency and security, as users can monitor activity and identify any unauthorized actions or determine who made a change. For each action taken, the log provides these details: * the timestamp when the action was taken * which user or API token took the action * what resource was acted upon (for example, a customer with ID 123) * what action was taken (for example, `add_plan`) * whether the action was successful You can access the Metronome audit log via the [/auditLogs](/api-reference/security/get-audit-logs) endpoint. Example records from the audit log: ```json theme={null} [ { "id": "4a893288-336f-4216-9f39-84362e4d20b0", "timestamp": "2023-04-32T18:31:55:00Z", "actor": { "id": "04b6506e-cb3c-43d4-912a-e9af03ad0f5b", "name": "Developer API token" }, "resource_type": "customer", "resource_id": "aa02b4b9-adde-414a-b303-5078fc4d23fc", "action": "add_plan", "request_id": "71f232b6-a236-466d-b89b-f9bn0b90940b", "status": "success" }, { "id": "f627572d-c5f1-4ba8-b227-093a901e787d", "timestamp": "2023-04-32T20:25:15:00Z", "actor": { "id": "b80922a0-f611-4bf9-8cb9-a47ce377826c", "name": "John Smith", "email": "john@example.com" }, "resource_type": "customer", "resource_id": "aa02b4b9-adde-414a-b303-5078fc4d23fc", "action": "change_name", "request_id": "99b4556d-1c82-435a-b6c6-ce239de22fe6", "status": "success" } ] ``` # Metronome's pricing model Source: https://docs.metronome.com/guides/platform-configuration/metronome-pricing-model Metronome charges are based on your actual usage of the platform. Your pricing consists of an annual platform fee for access to the services, plus consumption-based charges that accrue after you go live in production. This page defines the key concepts that appear on your Metronome invoice and in your order form. ## Pricing structure Metronome pricing has two components: * **Annual platform fee:** A fixed fee charged for access to the services. This fee doesn't count toward any consumption-based charge categories (Percentage of Billings, Events-based, Data Export, or Invoice Row Updates). * **Consumption-based charges:** Variable fees that depend on your usage of the services. These start accruing on your go-live date in the production instance. If your order form includes a **Consumption Commitment**, this is a pre-paid, non-refundable minimum commitment against your consumption-based charges. Any unused portion expires at the end of the Initial Service Term or any Renewal Service Term without refund or credit. ## Usage metrics ### Events An **Event** is a single usage event—each discrete JSON object submitted to and accepted by Metronome through the [ingestion API](/api-reference/ingest/ingest). Each event represents one measurable interaction on your platform, such as: * An API call * A storage measurement * A data transfer * Any other billable action ### Billings **Billings** are the total value of all invoices you generate through Metronome, whether invoiced automatically or generated by Metronome and invoiced manually. The following are excluded from your Billings total: * Invoices finalized within the current Metronome billing period that you void before Metronome invoices you * Invoices drafted in a non-production instance (for example, a Sandbox environment) for testing or demonstration * Zero-dollar invoices used to track free trial credits ## Data Export **Data Export** continuously syncs your Metronome billing and usage data into your own data warehouse or object storage destination. Use it for reporting, reconciliation, financial close, and custom analytics. ### How rows are counted A **Row Exported** is one row of data written by Metronome to your configured export destination, across any table type in the Data Export schema. How rows accumulate depends on the table type: | Table type | Behavior | | --------------- | ---------------------------------------------------------------------------------------------------------------------- | | **Incremental** | Only new or updated rows are exported in each sync cycle. | | **Snapshot** | All rows in the table are re-exported in each sync cycle. Each row in each full export cycle counts as a Row Exported. | ### Table categories Data Export tables are categorized as Standard or Premium: **Standard Data Export Tables** include: * Contracts tables * Contracts modification tables * Contracts pricing tables * Payments tables * Alerts tables * Finalized invoice tables * Customers tables * Events tables * Core entities tables **Premium Data Export Tables** include: * `draft_invoice` * `draft_line_item` * `breakdowns_draft_invoices` * `breakdowns_draft_line_items` * `breakdowns_invoices` (Finalized) * `breakdowns_line_items` (Finalized) * Rated Events (finalized and draft) Premium Data Export Tables may not all be currently available. Contact us via the [Metronome support portal](https://support.metronome.com/) for the latest availability. # Role-based access control (RBAC) Source: https://docs.metronome.com/guides/platform-configuration/role-based-access-rbac Role-based access control (RBAC) policies define how users interact with Metronome, what they are allowed to see, and what changes they are allowed to make. This increases your control over the data a user can access and the actions they can take. Implementing RBAC minimizes the scope of security vulnerabilities and reduces human error. **CUSTOM ROLES** We also support custom roles, allowing you to tailor permissions to your needs.