# 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](https://mintcdn.com/metronome-b35a6a36/WMVHzWf7d6M8Lnwb/images/manage-customers/manage-product-access.png?fit=max\&auto=format\&n=WMVHzWf7d6M8Lnwb\&q=85\&s=e3cba30e2dd6e19d4a8a490ff87df0f4) *** #### 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/free-trials/overview) *** #### 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) # Manage unbillable invoices Source: https://docs.metronome.com/guides/customers-billing/manage-customers/manage-unbillable-invoices Prevent select invoices from being sent to a billing provider. Use `unbillable_invoices_configuration` to control contract invoices Metronome sends to a downstream billing provider. Invoices that are not sent are still finalized in Metronome, but they are marked `unbillable` during normal processing. Common use cases include: * Suppressing overage invoices for a prepaid customer. * Suppressing scheduled invoices (i.e. commit installments) billed directly in a cloud marketplace. `unbillable_invoices_configuration` is set on a customer billing provider configuration. To apply a policy to a contract, first create a billing provider configuration with the rules you want, then assign that configuration to the contract. If you omit `unbillable_invoices_configuration`, it defaults to `[]` and all invoices are billable. Existing integrations are unaffected. ## Define unbillable invoice rules `unbillable_invoices_configuration` is an array of rules. Each rule identifies invoices that Metronome treats as unbillable. | Field | Required | Description | | :- | :- | :- | | `invoice_type` | Yes | The invoice type the rule applies to: `USAGE` or `SCHEDULED`. | | `fiat_credit_type_id` | Conditional | The fiat currency the rule applies to. Required when `max_amount` is set. Omit to create a catch-all rule that applies to every fiat currency for the `invoice_type`. | | `max_amount` | No | A positive number in the units of `fiat_credit_type_id`. Invoices with a total less than or equal to this amount are unbillable. Omit to make every matching invoice unbillable regardless of amount. | An empty array, `[]`, is valid and means all invoices are billable. ## Supported billing providers | Billing provider | `USAGE` rules | `SCHEDULED` rules | | :- | :-: | :-: | | Stripe | ✅ | ✅ | | NetSuite | ✅ | ✅ | | Marketplace (AWS / Azure / GCP) | ❌ | ✅ | ### Rule precedence For a given invoice type, Metronome first looks for a rule that matches the invoice's `fiat_credit_type_id`. If one exists, Metronome evaluates only that rule. If no currency-specific rule exists, Metronome evaluates the catch-all rule for that invoice type, if one is present. ### Validation Metronome validates rules when you create the billing provider configuration and returns an error if any of the following are violated: * Every rule must include `invoice_type`, set to `USAGE` or `SCHEDULED`. * `max_amount`, when present, must be a positive number. * A rule with `max_amount` must include `fiat_credit_type_id`. * For the same `invoice_type`, each fiat credit type can appear in at most one rule. * For the same `invoice_type`, at most one catch-all rule can omit `fiat_credit_type_id`. * Marketplace configurations only support `SCHEDULED` rules. ## Apply rules to a new contract ### Suppress all overage invoices Let's walk through an example for suppressing all overage invoices for a prepaid customer: **Step 1: Create the billing provider configuration** ```bash theme={null} curl https://api.metronome.com/v1/setCustomerBillingProviderConfigurations \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "data": [ { "customer_id": "8cecbf69-960f-4f66-9575-edebb7d95e88", "billing_provider": "stripe", "delivery_method": "direct_to_billing_provider", "configuration": { "stripe_customer_id": "cus_123", "stripe_collection_method": "charge_automatically" }, "unbillable_invoices_configuration": [ { "invoice_type": "USAGE" } ] } ] }' ``` **Step 2: Create a contract with the configuration** ```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", "starting_at": "2026-09-01T00:00:00.000Z", "rate_card_id": "d7abd0cd-4ae9-4db7-8676-e986a4ebd8dc", "billing_provider_configuration": { "billing_provider_configuration_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" } }' ``` All usage invoices on the new contract have a `billable_status` of `unbillable`. ### Send overages over a fixed amount Make USD usage invoices with totals up to 10 unbillable. USD usage invoices above 10 and all scheduled invoices remain billable. ```bash theme={null} curl https://api.metronome.com/v1/setCustomerBillingProviderConfigurations \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "data": [ { "customer_id": "8cecbf69-960f-4f66-9575-edebb7d95e88", "billing_provider": "stripe", "delivery_method": "direct_to_billing_provider", "configuration": { "stripe_customer_id": "cus_456", "stripe_collection_method": "charge_automatically" }, "unbillable_invoices_configuration": [ { "invoice_type": "USAGE", "fiat_credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "max_amount": 1000 } ] } ] }' ``` ### Example: Suppress scheduled invoices billed to a cloud marketplace ```bash theme={null} curl https://api.metronome.com/v1/setCustomerBillingProviderConfigurations \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "data": [ { "customer_id": "8cecbf69-960f-4f66-9575-edebb7d95e88", "billing_provider": "aws_marketplace", "delivery_method": "direct_to_billing_provider", "configuration": { "aws_customer_id": "cust_789", "aws_product_code": "my_product", "aws_region": "us-west-1" }, "unbillable_invoices_configuration": [ { "invoice_type": "SCHEDULED" } ] } ] }' ``` ## Apply rules to an existing contract To change the policy on an existing contract, create a new billing provider configuration with the appropriate billable settings. Then, schedule a change to the customer billing provider configuration on the contract, replacing the existing configuration with the new one created. ## Constraints and considerations > [!NOTE] > > **Draft invoice totals can switch from unbillable to billable.** For rules with `max_amount`, Metronome evaluates the invoice's current total, so a draft invoice's `billable_status` can change as its total changes. Once an invoice is finalized, its total and `billable_status` are stable. > [!NOTE] > > **You can manually send an unbillable Stripe invoice.** In the Metronome app, an authorized user can click **Send to Stripe** to send an individual unbillable invoice. After the invoice is sent, its `billable_status` is `billable`. This is only available for Stripe. > [!NOTE] > > **Voided and regenerated invoices use the original period's configuration.** When Metronome voids and regenerates an invoice, the regenerated invoice uses the billing provider configuration from the invoice's service period. # 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. > [!NOTE] > > **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. > [!NOTE] > > **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](https://mintcdn.com/metronome-b35a6a36/C_lGxKgdkdHt6xoX/images/manage-customers/provision-contract-fe412f3eebd53427e5c051a091504620.png?fit=max\&auto=format\&n=C_lGxKgdkdHt6xoX\&q=85\&s=f65fd32892d905d20bf0223a1c8b6350) 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 or, for `TODAY`, to the start of the current day in UTC (or the contract start, if that's later). 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 | Today | | :- | :-: | :-: | :-: | | null → Stripe | ✅ | ✅ | ✅ | | 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`, `START_OF_NEXT_PERIOD`, or `TODAY`. **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: Switch to a different Stripe configuration, effective today** `TODAY` takes effect at the start of the current day in UTC, or at the contract start if that's later. An invoice with a service period uses the new configuration if its service period ends after that time. An invoice without a service period uses it if it is issued at or after that time. So the current period's usage invoice moves to the new configuration, and an invoice without a service period that was issued before that time keeps its existing configuration. ```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": "TODAY" } } }' ``` **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 > [!NOTE] > > **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. `TODAY` is the exception: it resolves to the start of the current day in UTC, or the contract start if that's later, and is only supported when the current and new billing providers are each Stripe or null. Each invoice maps to exactly one billing provider configuration, based on the end of its service period (exclusive), or on its issue date when it has no service period. > [!NOTE] > > **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. > [!NOTE] > > **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. > [!NOTE] > > **`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. > [!NOTE] > > **A maximum of 10 schedule segments per contract.** If you need additional capacity on a specific contract, contact your account team. > [!NOTE] > > **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 > [!NOTE] > > **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://app.metronome.com/support) 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](https://mintcdn.com/metronome-b35a6a36/WMVHzWf7d6M8Lnwb/images/optimize-customer-experience/set-spend-limits-71e4ad74fa36b7482519de795e47af49.png?fit=max\&auto=format\&n=WMVHzWf7d6M8Lnwb\&q=85\&s=2e1a047da0bf0354680abb77d67176dd) 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" }' ``` > [!NOTE] > > **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/webhooks/best-practices). 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. > [!NOTE] > > 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://app.metronome.com/support) 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 →](/guides/customers-billing/demo-dashboard/app) ## 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://app.metronome.com/support). ### 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](https://mintcdn.com/metronome-b35a6a36/EFj4IzRwX7Op9TX1/images/optimize-customer-experience/usage-visibility-fdce11566d08bbcc48965b1e813ab849.png?fit=max\&auto=format\&n=EFj4IzRwX7Op9TX1\&q=85\&s=b784015e3251e6274db34023b96b5953) 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: > [accordion] View response > > ```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](https://mintcdn.com/metronome-b35a6a36/C_lGxKgdkdHt6xoX/images/optimize-customer-experience/commitment-tracking-ad8d69832510b0565b8fea1ce51e8d97.png?fit=max\&auto=format\&n=C_lGxKgdkdHt6xoX\&q=85\&s=bc6fa2cf97373149ae5649056a6b29ae) 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 }' ``` > [accordion] View response > > ```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](https://mintcdn.com/metronome-b35a6a36/EFj4IzRwX7Op9TX1/images/optimize-customer-experience/up-to-date-spend-79da8c8a70745d80275b7d649789844e.png?fit=max\&auto=format\&n=EFj4IzRwX7Op9TX1\&q=85\&s=0eb2e47a1182002c6ce818bc87314288) 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" ``` > [accordion] View response > > ```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. > [accordion] View response > > ```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](https://mintcdn.com/metronome-b35a6a36/C_lGxKgdkdHt6xoX/images/optimize-customer-experience/embed-invoice-dashboard-d7f7d0437f79ff47d7fb1ef59c7b0494.png?fit=max\&auto=format\&n=C_lGxKgdkdHt6xoX\&q=85\&s=7af99751ce28ec6bbbe1dae1a182dee3) 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](https://mintcdn.com/metronome-b35a6a36/EFj4IzRwX7Op9TX1/images/optimize-customer-experience/embed-usage-dashboard-9bdb8b6e399a006c498765506e018ca9.png?fit=max\&auto=format\&n=EFj4IzRwX7Op9TX1\&q=85\&s=3b5cde91dfff0508ecd8d56af89a8ffc) ### 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](https://mintcdn.com/metronome-b35a6a36/C_lGxKgdkdHt6xoX/images/optimize-customer-experience/embed-commits-and-credits-dashboard-31100d4112d26f01012abcebef08dda4.png?fit=max\&auto=format\&n=C_lGxKgdkdHt6xoX\&q=85\&s=ca2ebc5369e89ee6d96890af06b3c6db) ### 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](https://mintcdn.com/metronome-b35a6a36/C_lGxKgdkdHt6xoX/images/optimize-customer-experience/embed-style-guide-invoice-e2934a0c3c5f3dc8435e75c0cfa96e8a.png?fit=max\&auto=format\&n=C_lGxKgdkdHt6xoX\&q=85\&s=6c9457039468a6c19eab0d0cf5870848) # 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. > [!WARNING] > > 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: > [card] > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >
TypeTimestampAmount
`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 > [card] > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >
TypeDescription
`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 > [card] > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >
TypeDescription
`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`. > [!WARNING] > > **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. > [!NOTE] > > **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 } } } ``` > [!NOTE] > > **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. > [!NOTE] > > **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 > [!WARNING] > > **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, `low_remaining_contract_credit_and_commit_balance_reached` and `low_remaining_contract_credit_and_commit_percentage_reached` alerts evaluate the **combined** balance or remaining percentage of all active commits and credits for a customer. When that value 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 or percentage 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` or `low_remaining_contract_credit_and_commit_percentage_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 combined balance or percentage alert using `alert_specifiers` applicable to that credit or commit. The following examples use combined balance alerts. The same inclusion, exclusion, and grouping behavior applies to combined percentage alerts. ### 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. > [!NOTE] > > **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. > [!NOTE] > > **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" } ] } ] } } ``` > [!NOTE] > > **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://app.metronome.com/support) 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. > [!NOTE] > > **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` or `low_remaining_contract_credit_and_commit_percentage_resolved` webhook when an alert returns to `OK` from `IN_ALARM`. Contact us via the [Metronome support portal](https://app.metronome.com/support) 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 or subscription 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/webhooks/best-practices) 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). > [!NOTE] > > **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. > [!NOTE] > > To request higher limits for your Metronome account, please contact us via the [Metronome support portal](https://app.metronome.com/support). ## 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 > [!NOTE] > > **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. You can create an offset for a supported [system notification type](/guides/customers-billing/set-up-notifications/system-notifications). Invoice, product, and rate card notifications do not support offsets. 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](https://mintcdn.com/metronome-b35a6a36/phb9Acjv7jlF___r/images/set-up-notification/offset_create.png?fit=max\&auto=format\&n=phb9Acjv7jlF___r\&q=85\&s=d7f226206d47cd73ee32a20cea1de3a0) **In the UI** 1. Navigate to the **Notifications** tab 2. Click **Create Notification** 3. Choose a system notification type that supports offsets 4. Configure offset details (e.g. 3 days after contract starts, 60 days before commit segment ends, 7 days before subscription 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 > [!NOTE] > > **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. Adding or updating contract custom fields does not trigger this notification. | | 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. Adding or updating commit custom fields does not trigger this notification. | | 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. Adding or updating credit custom fields does not trigger this notification. | | 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 | | Subscription | `subscription.create` | Triggers when a new subscription is created on a contract | | Subscription | `subscription.start` | Triggers when a subscription starts | | Subscription | `subscription.end` | Triggers when a subscription ends | | Invoice | `invoice.void` | Triggers when an invoice is voided | | Product | `product.edit` | Triggers when a product is edited | | Rate card | `rate_card.create` | Triggers when a rate card is created | | Rate card | `rate_card.edit` | Triggers when rate card metadata is edited For example, this notification triggers when you update the rate card name or rate card alias. | | Rate card | `rate_card.archive` | Triggers when a rate card is archived | | Rate card | `rate_card.rates_changed` | Triggers when one or more rates on a rate card change | Invoice, product and rate card notifications apply across your Metronome account and do not support offsets. The `rate_card.rates_changed` payload includes `earliest_effective_at`, the earliest effective time among the changed rates. ## 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" } } ``` ```json subscription.create theme={null} { "id": "b7e2f1a4-3c5d-5e6f-8a9b-0c1d2e3f4a5b", "type": "subscription.create", "timestamp": "2026-10-01T15:30:00Z", "environment_type": "PRODUCTION", "subscription_id": "6a1f8c3e-2b4d-4e5f-9a7b-8c9d0e1f2a3b", "subscription_custom_fields": { "seat_type": "developer" }, "starting_at": "2026-11-01T00:00:00Z", "ending_before": null, "payment_gate_config": { "payment_gate_type": "STRIPE", "tax_type": "STRIPE" }, "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 subscription.start theme={null} { "id": "c8f3a2b5-4d6e-5f7a-9b0c-1d2e3f4a5b6c", "type": "subscription.start", "timestamp": "2026-11-01T00:00:00Z", "environment_type": "PRODUCTION", "subscription_id": "6a1f8c3e-2b4d-4e5f-9a7b-8c9d0e1f2a3b", "subscription_custom_fields": { "seat_type": "developer" }, "starting_at": "2026-11-01T00:00:00Z", "payment_gate_config": { "payment_gate_type": "STRIPE", "tax_type": "STRIPE" }, "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 subscription.end theme={null} { "id": "d9a4b3c6-5e7f-5a8b-9c1d-2e3f4a5b6c7d", "type": "subscription.end", "timestamp": "2027-01-01T00:00:00Z", "environment_type": "PRODUCTION", "subscription_id": "7b2a9d4f-3c5e-4f6a-8b9c-0d1e2f3a4b5c", "subscription_custom_fields": { "seat_type": "admin" }, "ending_before": "2027-01-01T00:00:00Z", "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 invoice.void theme={null} { "id": "38498915-c390-4c23-b13b-d6de5bfaadce", "type": "invoice.void", "timestamp": "2026-10-15T12:00:00Z", "environment_type": "PRODUCTION", "invoice_id": "958c06cf-dafb-4190-be8d-86f010f6bbe5", "invoice_type": "USAGE", "invoice_custom_fields": { "purchase_order": "PO-123" }, "contract_id": "4066aa52-4c2f-4145-9023-afe5fa7b4a62", "contract_custom_fields": { "plan": "enterprise" }, "customer_id": "cedde3ab-5bf2-4176-83a7-1767671ad514", "customer_custom_fields": { "region": "us-west" } } ``` ```json product.edit theme={null} { "id": "7a1d20c4-02a8-4aa4-a60f-63a13f1fd240", "type": "product.edit", "timestamp": "2026-09-30T19:30:00Z", "environment_type": "PRODUCTION", "product_id": "68a1bc71-452a-4f1d-b4da-a51ef021be32", "custom_fields": { "product_type": "standard" } } ``` ```json rate_card.create theme={null} { "id": "4d7f6d2a-f149-4a89-9917-4f4cb29ca198", "type": "rate_card.create", "timestamp": "2026-09-16T19:30:00Z", "environment_type": "PRODUCTION", "rate_card_id": "2c7c7f4b-63ac-43bf-8c42-676298471cea", "custom_fields": { "rate_card_type": "standard" } } ``` ```json rate_card.edit theme={null} { "id": "5e8a7e3b-a250-4b9a-a228-5f5dc3ad9b29", "type": "rate_card.edit", "timestamp": "2026-09-16T19:35:00Z", "environment_type": "PRODUCTION", "rate_card_id": "2c7c7f4b-63ac-43bf-8c42-676298471cea", "custom_fields": { "rate_card_type": "standard" } } ``` ```json rate_card.archive theme={null} { "id": "6f9b8f4c-b361-4cab-b339-6f6ed4bea13a", "type": "rate_card.archive", "timestamp": "2026-09-16T19:40:00Z", "environment_type": "PRODUCTION", "rate_card_id": "2c7c7f4b-63ac-43bf-8c42-676298471cea", "custom_fields": { "rate_card_type": "standard" } } ``` ```json rate_card.rates_changed theme={null} { "id": "91ab4d1c-5962-4252-a21d-dab9e88868ee", "type": "rate_card.rates_changed", "timestamp": "2026-09-16T19:45:00Z", "environment_type": "PRODUCTION", "rate_card_id": "2c7c7f4b-63ac-43bf-8c42-676298471cea", "custom_fields": { "rate_card_type": "standard" }, "earliest_effective_at": "2026-10-01T00:00:00Z" } ``` ## 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](https://mintcdn.com/metronome-b35a6a36/phb9Acjv7jlF___r/images/set-up-notification/notiifcations_list.png?fit=max\&auto=format\&n=phb9Acjv7jlF___r\&q=85\&s=a933a4ab80194beeacde9697912cfd03) **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 a `policy` object with the `type` of the system notification and `is_enabled` set to `true`. Omit `id`, which applies only to offset notifications ```json theme={null} { "policy": { "type": "contract.create" }, "is_enabled": true } ``` 3. A successful response will return a 200 response code ```json theme={null} { "data": { "type": "SYSTEM_LIFECYCLE_EVENT", "is_enabled": true, "policy": { "type": "contract.create" } } } ``` > [!NOTE] > > **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. > [!NOTE] > > **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 > [accordion] Commit & Credit Notifications > > #### 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. > > #### Contract credit and commit percentage > > **Alert Type:** `alerts.low_remaining_contract_credit_and_commit_percentage_reached` > > Triggers when a customer's combined commit and credit percentage reaches or drops below a set percentage. If multiple commits and credits exist for a customer, Metronome sums the remaining balances and original amounts across all commits and credits to calculate the percentage compared 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. > [accordion] Spend & Usage Notifications > > #### 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. > [accordion] Invoice Notifications > > #### 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](https://mintcdn.com/metronome-b35a6a36/phb9Acjv7jlF___r/images/set-up-notification/threshold_create.png?fit=max\&auto=format\&n=phb9Acjv7jlF___r\&q=85\&s=4853446e2cd40b8c9f7bd488241e0d44) **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. > [!WARNING] > > **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://app.metronome.com/support) 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](https://mintcdn.com/metronome-b35a6a36/AzoEmRc69c1nBkjv/images/docs/guides/implement-metronome/event-stream.png?fit=max\&auto=format\&n=AzoEmRc69c1nBkjv\&q=85\&s=d7235e8d5f6a47329cf2ae6c45700e20) ![Event summary in Metronome UI](https://mintcdn.com/metronome-b35a6a36/RmXuQ2v0AyTvK_BJ/images/docs/guides/implement-metronome/event-summary.png?fit=max\&auto=format\&n=RmXuQ2v0AyTvK_BJ\&q=85\&s=9fd66d6d671396c5bce0769b65c75df2) ## 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 to /ingest 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. > [!NOTE] > > 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. > [!WARNING] > > 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://app.metronome.com/support) 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. > [!WARNING] > > 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://app.metronome.com/support) 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. # Send usage events in bulk Source: https://docs.metronome.com/guides/events/send-usage-events-bulk Use Bulk Data Ingest to send historical or batch usage to Metronome in JSONL files. Bulk Data Ingest uses the same event structure as [`/ingest`](/api/#operation/ingest-v1), but processes files asynchronously. > [!NOTE] > > Bulk Data Ingest is currently in private preview. Contact your Metronome representative for access. ## When to use Bulk Data Ingest Use Bulk Data Ingest for usage that does not fit a real-time ingestion workflow: * **Migrate to Metronome:** Import historical usage from a previous billing or metering system. * **Recover missing usage:** Backfill events that were not delivered because of a pipeline failure or reporting issue. * **Report usage on a schedule:** Submit usage monthly, quarterly, or on another schedule when events are not available in real time. * **Support self-hosted and air-gapped deployments:** Import usage from environments that cannot connect to Metronome's `/ingest` endpoint. Use the `/ingest` API for ongoing, real-time usage reporting. ## Before you upload Create the relevant customers, ingest aliases, and billable metrics in Metronome before uploading usage. Prepare an uncompressed JSONL file with one event per line. Each event must follow the `/ingest` event schema: ```jsonl theme={null} {"transaction_id":"event-001","customer_id":"customer-123","timestamp":"2026-08-01T00:00:00Z","event_type":"api_request","properties":{"requests":"10"}} {"transaction_id":"event-002","customer_id":"customer-123","timestamp":"2026-08-01T01:00:00Z","event_type":"api_request","properties":{"requests":"25"}} ``` Only uncompressed `.jsonl` files are supported. Keep each file no larger than 5 GB. Split larger datasets across multiple files. Do not overwrite a file after you upload it. If a file fails validation, fix the reported errors and upload a new file with a different name. Bulk Data Ingest cannot change an event that Metronome has already processed. ## Validate files locally The following sample file follows the required format: ```jsonl bulk-ingest-example.jsonl theme={null} {"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"}} {"transaction_id":"event-20250910-003","customer_id":"customer_789","timestamp":"2025-09-10T12:17:00Z","event_type":"ai-run","properties":{"model_name":"gpt-4-mini","input_tokens":"12000","output_tokens":"1100","type":"output"}} ``` Validate each file before uploading it. Confirm that: * Each line contains one valid JSON object. * Every event includes `transaction_id`, `customer_id`, `timestamp`, and `event_type`. * Timestamps use RFC 3339 format. * Timestamps are not in the future and are no more than one year old. * Each `customer_id` matches a Metronome customer ID or ingest alias. * Property keys and values are strings, including numeric values. * The file does not contain duplicate `transaction_id` values. * The file is uncompressed JSONL and no larger than 5 GB. Metronome validates the complete file before processing any events. If any event fails validation, Metronome rejects the complete file. ## Use idempotent transaction IDs Use a deterministic `transaction_id` for each event. If you resend an event, keep its `transaction_id` and `timestamp` unchanged. Do not reuse a transaction ID for a different event. Metronome uses the `transaction_id` to identify duplicate events. For periodic measurements such as heartbeats, you can construct the transaction ID from the source system, entity, and measurement period: ``` __ ``` For example, `billing_node42_2025031008` identifies a heartbeat from node 42 for the 8:00 AM measurement period on March 10, 2025. Duplicate transaction IDs within one file cause the complete file to fail validation. Across files, Metronome ignores duplicate events with the same `transaction_id`. Metronome checks for duplicates against events with a `timestamp` in the past year, regardless of when those events were uploaded. Do not rely on upload order to determine which event Metronome processes. ## Use /ingest and Bulk Data Ingest together You can use `/ingest` and Bulk Data Ingest for the same customer. Bulk Data Ingest accepts events of any age up to one year. Metronome selects the processing pipeline based on each event's timestamp: events within `/ingest`'s 34-day backdating window use standard ingestion, and earlier events use historical ingestion. If a bulk file contains both, Metronome routes each event automatically. Historical ingestion checks each `transaction_id` against events previously received through `/ingest`. If Metronome finds a match, it ignores the event from the bulk file. If you send the same event through both methods, keep its `transaction_id` and `timestamp` unchanged. The `/ingest` endpoint does not check historical events for duplicates. It accepts events within its 34-day backdating window, while historical ingestion handles events from before that window. ## Processing and verification Bulk Data Ingest processes files asynchronously. Events do not appear immediately after you upload a file. Wait for processing to finish before reviewing usage or generating an invoice that depends on the imported events. You cannot currently check upload status through the API or the Metronome application. After processing finishes, events appear in: * Event search * Usage graphs and breakdowns * Billing calculations for invoices that have not been finalized * Error usage reporting Bulk events do not appear when event search is filtered to a specific billable metric. > [!WARNING] > > Bulk ingestion can affect alerts as events are processed. Review your alert configuration before uploading a large historical dataset. ## How imported usage affects invoices Imported usage affects invoices that have not been finalized. It does not automatically update an invoice that has already been finalized. If a finalized invoice needs to include the imported usage, void and regenerate the invoice after processing finishes. ## Limits and requirements * **Supported format:** Uncompressed JSONL * **Maximum file size:** 5 GB * **Event timestamps:** Up to one year before upload * **Future events:** Not supported * **Processing:** Asynchronous * **File validation:** Metronome rejects the complete file if any event fails validation * **Duplicate transaction IDs:** Metronome rejects a file containing duplicate `transaction_id` values * **Finalized invoices:** Not updated automatically # Build with agent skills Source: https://docs.metronome.com/guides/get-started/agent-skills Install Metronome agent skills so AI coding agents build more accurate Metronome integrations. Agent skills give AI coding agents reusable guidance for specific tasks. Metronome agent skills encode recommended integration patterns, API request formats, and common pitfalls agents should avoid. Install them in Claude Code, Cursor, Codex, or any other coding agent that supports skills. ## Installation To start building with Metronome agent skills, run this command from your project directory: ```bash theme={null} npx skills add https://docs.metronome.com ``` The command will then prompt you to choose which skills to install and which agents to install them for. > [!NOTE] > > Installed skills don't update automatically. Run `npx skills update -y` to get the latest versions. ## Provide your API token Skills that read from or write to your Metronome environment require an API token. 1. [Create an API token](/api-reference/authentication). 2. Export it as `METRONOME_BEARER_TOKEN`, the same variable the [Metronome SDKs](/guides/get-started/developer-sdks) read: ```bash theme={null} export METRONOME_BEARER_TOKEN="your-api-token" ``` 3. If you use a terminal agent such as Claude Code or Codex, start it from the same shell. For an IDE-based agent, set the variable where the IDE reads its environment, then restart the IDE. Keep the token out of your agent's chat and out of any file your agent might commit. Load it from an environment variable or a secrets manager instead. API tokens inherit the permissions of the user who created them, so consider a token [scoped](/api-reference/authentication#permissions) to read-only access or to your sandbox environment. ## Skills index See the [index of Metronome skills](https://docs.metronome.com/.well-known/skills/index.json). ## See also > [card] [API reference](/api-reference/introduction) > > Endpoints, request parameters, and response fields > [card] [Billing for LLM tokens](/guides/pricing-packaging/billing-model-guides/token-billing) > > Set up token billing with the token billing skill # 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](https://mintcdn.com/metronome-b35a6a36/5Bk8n4-cg6am9tRU/images/docs/guides/implement-metronome/metronome_core_objects_diagram.png?fit=max\&auto=format\&n=5Bk8n4-cg6am9tRU\&q=85\&s=8e89fd156d1dfd579204f97014c1a516) 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_BEARER_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_BEARER_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) > [!WARNING] > > **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_BEARER_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_BEARER_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_BEARER_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_BEARER_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_BEARER_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_BEARER_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_BEARER_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 > [!TIP] > > 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/webhooks/best-practices) — 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](https://mintcdn.com/metronome-b35a6a36/C_lGxKgdkdHt6xoX/images/docs/get-started/developer-sdks/sdk-view-event-73e1747ae1551477facc43cbc57b5d41.png?fit=max\&auto=format\&n=C_lGxKgdkdHt6xoX\&q=85\&s=017cf4abb448c3abe89a5ad4dbbaf81f) ## 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](https://mintcdn.com/metronome-b35a6a36/C_lGxKgdkdHt6xoX/images/docs/get-started/developer-sdks/sdk-billable-metric-548bf969fd6260246719c508d04edbbf.png?fit=max\&auto=format\&n=C_lGxKgdkdHt6xoX\&q=85\&s=a615b65747c42de87f38c753ea07c3ac) 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](https://mintcdn.com/metronome-b35a6a36/C_lGxKgdkdHt6xoX/images/docs/get-started/developer-sdks/sdk-billable-metric-event-685727864059c82397e970c9313d34c3.png?fit=max\&auto=format\&n=C_lGxKgdkdHt6xoX\&q=85\&s=d0727253a057d5478a33d180b6954873) ## 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](https://mintcdn.com/metronome-b35a6a36/C_lGxKgdkdHt6xoX/images/docs/get-started/developer-sdks/sdk-customer-8951c5c90f6d572acfe0b66fb69c375a.png?fit=max\&auto=format\&n=C_lGxKgdkdHt6xoX\&q=85\&s=d8af08c4c5d5262faa8eb79a96e2b6eb) 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](https://mintcdn.com/metronome-b35a6a36/C_lGxKgdkdHt6xoX/images/docs/get-started/developer-sdks/sdk-billable-metric-customer-9c43209722c86ae10d972b5674713926.png?fit=max\&auto=format\&n=C_lGxKgdkdHt6xoX\&q=85\&s=45ea14337b820d74f32097f151b69f19) ## 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](https://mintcdn.com/metronome-b35a6a36/C_lGxKgdkdHt6xoX/images/docs/get-started/developer-sdks/sdk-billable-metric-millions-19186d5f83b1cdad82704ab369e73138.png?fit=max\&auto=format\&n=C_lGxKgdkdHt6xoX\&q=85\&s=84d142db2088f3ec102cc278c58125ee) 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](https://mintcdn.com/metronome-b35a6a36/C_lGxKgdkdHt6xoX/images/docs/get-started/developer-sdks/sdk-contract1-1baf22de9680a77ea8381e4f6ac75422.png?fit=max\&auto=format\&n=C_lGxKgdkdHt6xoX\&q=85\&s=a695f736680ef497f5278d9e900b3fe9) 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](https://mintcdn.com/metronome-b35a6a36/C_lGxKgdkdHt6xoX/images/docs/get-started/developer-sdks/sdk-contract2-e0955e079cd3ef6724b4770bc0227a10.png?fit=max\&auto=format\&n=C_lGxKgdkdHt6xoX\&q=85\&s=bd412035d28304ec4a363217f58883f9) # Metronome Docs Source: https://docs.metronome.com/guides/get-started/home > [card] [How Metronome works](/guides/get-started/how-metronome-works) > > Understand the core parts of Metronome > [card] [Quickstart guide](/guides/get-started/metronome-dashboard-quickstart) > > Get to your first invoice on Metronome > [card] [Plan your billing architecture](/guides/implement-metronome/planning-your-billing-architecture) > > What to keep in mind as you create your billing architecture [Try Metronome](https://signup.metronome.com/) > [card] [Build with AI coding agents](/guides/get-started/agent-skills) > > Install Metronome agent skills so Claude Code, Cursor, Codex, and other > coding agents build more accurate Metronome integrations. # Build your pricing and packaging > [tab] Pay-as-you-go billing > > Pay-as-you-go billing > > Set up Metronome to support charging your customers in arrears for > only what they use. > > [Open the guide ](/guides/pricing-packaging/billing-model-guides/pay-as-you-go) > > ![Metronome logo pointing at an invoice](https://mintcdn.com/metronome-b35a6a36/C_lGxKgdkdHt6xoX/images/homepage/guides.png?fit=max\&auto=format\&n=C_lGxKgdkdHt6xoX\&q=85\&s=f481e78ce8d7383985fcf403fdc1eece) > [tab] Enterprise commits > > Enterprise commits > > Set up Metronome to support enterprise deal requirements like prepaid > and postpaid commitments, negotiated discounts, one-time charges, > contract renewals, and more. > > [Open the guide ](/guides/pricing-packaging/billing-model-guides/enterprise-commit) > > ![Metronome logo pointing at an invoice](https://mintcdn.com/metronome-b35a6a36/C_lGxKgdkdHt6xoX/images/homepage/guides.png?fit=max\&auto=format\&n=C_lGxKgdkdHt6xoX\&q=85\&s=f481e78ce8d7383985fcf403fdc1eece) > [tab] Subscriptions w/ usage > > Subscriptions w/ usage > > Set up Metronome to combine recurring revenue with usage-based > components. > > [Open the guide ](/guides/pricing-packaging/billing-model-guides/hybrid-business-models) > > ![Metronome logo pointing at an invoice](https://mintcdn.com/metronome-b35a6a36/C_lGxKgdkdHt6xoX/images/homepage/guides.png?fit=max\&auto=format\&n=C_lGxKgdkdHt6xoX\&q=85\&s=f481e78ce8d7383985fcf403fdc1eece) > [tab] Pre-paid credits > > 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. > > [Open the guide ](/guides/pricing-packaging/billing-model-guides/prepaid-credits) > > ![Metronome logo pointing at an invoice](https://mintcdn.com/metronome-b35a6a36/C_lGxKgdkdHt6xoX/images/homepage/guides.png?fit=max\&auto=format\&n=C_lGxKgdkdHt6xoX\&q=85\&s=f481e78ce8d7383985fcf403fdc1eece) # Get started with > [card] [Contracts](/guides/get-started/core-concepts/provision-contract#create-a-contract%E2%80%8B) > [card] [Invoicing](/guides/get-started/core-concepts/how-invoicing-works) > [card] [Rev-rec](/guides/reporting-insights/financial-reporting/revenue-recognition) # 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](https://mintcdn.com/metronome-b35a6a36/C_lGxKgdkdHt6xoX/images/docs/get-started/how-metronome-works/metronome-invoice-objects-7f5d9996d490ccb2f643473c592ece9a.png?fit=max\&auto=format\&n=C_lGxKgdkdHt6xoX\&q=85\&s=7c71d672055f1008ca41282799ee7a19) 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](https://mintcdn.com/metronome-b35a6a36/C_lGxKgdkdHt6xoX/images/docs/get-started/how-metronome-works/objects-table-25dcd8552d736601c20d7ef163a3910f.png?fit=max\&auto=format\&n=C_lGxKgdkdHt6xoX\&q=85\&s=8f372ffd1a10cfdc3a49374a059edcd3) 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](https://mintcdn.com/metronome-b35a6a36/C_lGxKgdkdHt6xoX/images/docs/get-started/how-metronome-works/billable_metric_diagram-49f92894ca48dae35f0d2fc47a642e02.png?fit=max\&auto=format\&n=C_lGxKgdkdHt6xoX\&q=85\&s=3259da51c2a22684428a70928f88f075) > **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](https://mintcdn.com/metronome-b35a6a36/C_lGxKgdkdHt6xoX/images/docs/get-started/how-metronome-works/products_diagram-f2766fbc59707cfcfc68ad9071d153ec.png?fit=max\&auto=format\&n=C_lGxKgdkdHt6xoX\&q=85\&s=af2edbdaa187dacd31ce50383f62fbd7) 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](https://mintcdn.com/metronome-b35a6a36/C_lGxKgdkdHt6xoX/images/docs/get-started/how-metronome-works/rate_cards_diagram-120a8ab65c3f51bfd6cc7d81694c3335.png?fit=max\&auto=format\&n=C_lGxKgdkdHt6xoX\&q=85\&s=6a998df6e2d07e63ebe5ad78e6298b0d) 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](https://mintcdn.com/metronome-b35a6a36/C_lGxKgdkdHt6xoX/images/docs/get-started/how-metronome-works/delete-me-temp-rate-cards-0e3d1d15defc0bc01c3596f1e5a8b246.png?fit=max\&auto=format\&n=C_lGxKgdkdHt6xoX\&q=85\&s=092922303896ebf5df084bbe13cc7b7a) > [!TIP] > > **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](https://mintcdn.com/metronome-b35a6a36/C_lGxKgdkdHt6xoX/images/docs/get-started/how-metronome-works/contracts_diagram-6808351b131abb7d4150ab8319c72f2a.png?fit=max\&auto=format\&n=C_lGxKgdkdHt6xoX\&q=85\&s=9cdad7407314fbc15ab42b75897bdc37) 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. > [!TIP] > > **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](https://mintcdn.com/metronome-b35a6a36/C_lGxKgdkdHt6xoX/images/docs/get-started/how-metronome-works/invoices_diagram-128b100eff93a612e6601886ed89ae55.png?fit=max\&auto=format\&n=C_lGxKgdkdHt6xoX\&q=85\&s=4e324acfce704f3d82c86b5690c68db2) ## 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](https://mintcdn.com/metronome-b35a6a36/5Bk8n4-cg6am9tRU/images/docs/guides/implement-metronome/metronome_core_objects_diagram.png?fit=max\&auto=format\&n=5Bk8n4-cg6am9tRU\&q=85\&s=8e89fd156d1dfd579204f97014c1a516) 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](https://mintcdn.com/metronome-b35a6a36/5Bk8n4-cg6am9tRU/images/docs/guides/implement-metronome/example_event_payload.png?fit=max\&auto=format\&n=5Bk8n4-cg6am9tRU\&q=85\&s=4e166a99b9b32e6756acb984af12325d) > [!TIP] > > **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`). > [!WARNING] > > 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) > [!WARNING] > > **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**. > [!TIP] > > 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. > [!TIP] > > 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) > [!TIP] > > 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](https://mintcdn.com/metronome-b35a6a36/5Bk8n4-cg6am9tRU/images/docs/guides/implement-metronome/test_events_payload.png?fit=max\&auto=format\&n=5Bk8n4-cg6am9tRU\&q=85\&s=b54551b42e0a6c9fb46a960d5545426c) 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/webhooks/webhook-types#webhook-types) to listen to payment statuses for payment-gated commits. > [!TIP] > > 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/webhooks/webhook-types) — 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 > [!NOTE] > > **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] > > **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] > > **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://app.metronome.com/support). # 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](https://mintcdn.com/metronome-b35a6a36/84OZCN1rCXvkxNrS/images/docs/get-started/core-concepts/billable-metrics/create_streaming_bm.png?fit=max\&auto=format\&n=84OZCN1rCXvkxNrS\&q=85\&s=08d9f7fe44e841095ecb7558c00527df) 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. > [!NOTE] > > **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 ``` > [!NOTE] > > **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](https://mintcdn.com/metronome-b35a6a36/TrrblT2KR7zYyGbN/images/docs/get-started/core-concepts/billable-metrics/billable-metrics-1-be008dcf69b0ae2a81d99524274fe228.png?fit=max\&auto=format\&n=TrrblT2KR7zYyGbN\&q=85\&s=ecb3da455d873e1aee54c2711b1315bf) 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 …)`. > [!NOTE] > > **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://app.metronome.com/support) 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. > [!NOTE] > > **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://app.metronome.com/support) 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]` . > [!NOTE] > > **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://app.metronome.com/support) 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. > [!NOTE] > > **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](https://mintcdn.com/metronome-b35a6a36/TrrblT2KR7zYyGbN/images/docs/get-started/core-concepts/rate-cards/rate_cards_diagram-120a8ab65c3f51bfd6cc7d81694c3335.png?fit=max\&auto=format\&n=TrrblT2KR7zYyGbN\&q=85\&s=9a3d2fb51d7cc2889496f0c8d64c4d32) ## 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] > > **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](https://mintcdn.com/metronome-b35a6a36/C_lGxKgdkdHt6xoX/images/docs/get-started/core-concepts/rate-cards/sample-rate-card-3a41126b2e411e72ddbf6d41b94a7cf5.png?fit=max\&auto=format\&n=C_lGxKgdkdHt6xoX\&q=85\&s=31f8bd0484e4c0414b38361a46036318) ### 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://app.metronome.com/support). ### 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 | > [!NOTE] > > **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](https://mintcdn.com/metronome-b35a6a36/TrrblT2KR7zYyGbN/images/docs/get-started/core-concepts/products/products_diagram-f2766fbc59707cfcfc68ad9071d153ec.png?fit=max\&auto=format\&n=TrrblT2KR7zYyGbN\&q=85\&s=1d464ba9a88576fc7881821b9c019b2f) 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. > [!NOTE] > > **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. > [!NOTE] > > **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://app.metronome.com/support) 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. > [!NOTE] > > **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`. > [!NOTE] > > **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://app.metronome.com/support) 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. > [!NOTE] > > **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: > [!NOTE] > > 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](https://mintcdn.com/metronome-b35a6a36/TrrblT2KR7zYyGbN/images/docs/get-started/core-concepts/invoicing/invoice-visualization-0c80fcdcdf83c0cc8f24897d213a430b.png?fit=max\&auto=format\&n=TrrblT2KR7zYyGbN\&q=85\&s=0431ce544e3a1341a73878b3003ca9fe) ## 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](https://mintcdn.com/metronome-b35a6a36/TrrblT2KR7zYyGbN/images/docs/get-started/core-concepts/invoicing/invoice-pricing-group-keys-8a6bf1ee9499a71314f996c72c90e2fa.png?fit=max\&auto=format\&n=TrrblT2KR7zYyGbN\&q=85\&s=784fd04d6060a68d51197eba5786e077) 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](https://mintcdn.com/metronome-b35a6a36/TrrblT2KR7zYyGbN/images/docs/get-started/core-concepts/invoicing/invoice-presentation-group-keys-6fb71250f9fd6c7e1302157df51a349d.png?fit=max\&auto=format\&n=TrrblT2KR7zYyGbN\&q=85\&s=10b6e816f60da5156d875b6a05622158) # 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**. > [!WARNING] > > 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**. > [!WARNING] > > **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. > [!TIP] > > 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. > [!NOTE] > > **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":[{ "subscription_alias":"starter_subscription", "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" }, }] }' ``` > [!NOTE] > > **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. You can also customize a package when provisioning a customer, by: * Setting initial quantity or initial `seat_ids` for a subscription on the package * Adding any term, including overrides, recurring credits commits, scheduled charges, etc * Using contract transitions to end an existing contract and start a new contract simultaneously. For example, use this API call to set the initial quantity for the Starter Plan to 10: ```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", "package_customizations": { "modify_subscriptions": [ { "subscription_alias": "starter_subscription", "initial_quantity": 10 } ] } }' ``` ## 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. > [!WARNING] > > **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](https://mintcdn.com/metronome-b35a6a36/TrrblT2KR7zYyGbN/images/docs/get-started/core-concepts/provision-contract/provision-contract-fe412f3eebd53427e5c051a091504620.png?fit=max\&auto=format\&n=TrrblT2KR7zYyGbN\&q=85\&s=e1cb4fad3f87c0ae87d99bc5d241d0b9) 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" } }' ``` > [!NOTE] > > **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. > [!NOTE] > > **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. > [!NOTE] > > **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. > [!NOTE] > > **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. > [!NOTE] > > **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. > [!WARNING] > > **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://app.metronome.com/support) 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. > [!WARNING] > > **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://app.metronome.com/support) 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. > [card] [Designing your events](https://docs.metronome.com/guides/events/design-usage-events) > [card] [High volume data ingestion](https://docs.metronome.com/guides/events/high-volume-ingestion) ## 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? > [card] [Pay-as-you-go Billing](https://docs.metronome.com/launch-guides/pay-go/) > [card] [Enterprise Commits](https://docs.metronome.com/launch-guides/enterprise-commit/) > [card] [Subscriptions w/ Usage](https://docs.metronome.com/launch-guides/hybrid-business/) > [card] [Pre-Paid Credits](https://docs.metronome.com/launch-guides/prepaid-credits/) ## 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 > [card] [Build in-app reports](https://docs.metronome.com/guides/reporting-insights/in-app-reporting) > [card] [Set notifications](https://docs.metronome.com/guides/customers-billing/set-up-notifications/create-and-manage-notifications) > [card] [Revenue recognition](https://docs.metronome.com/guides/reporting-insights/financial-reporting/revenue-recognition) ## 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 meteringInvoice 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 setupPricing 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 flowsCustomers 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 environmentBefore 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 handlingBilling is only reliable if your system knows when things go wrong or statuses change. [Webhooks](https://docs.metronome.com/guides/platform-configuration/webhooks/webhook-types) 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 monitoringYou 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 exportData 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 testFinally, 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] > > **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 } ``` > [!NOTE] > > **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. > [!NOTE] > > 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.** > [!NOTE] > > **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](https://mintcdn.com/metronome-b35a6a36/TrrblT2KR7zYyGbN/images/docs/Invoices/void-invoice-2327efe6cbdb93c2eb421a9b5d5fa25d.png?fit=max\&auto=format\&n=TrrblT2KR7zYyGbN\&q=85\&s=63663fb1d89867cd7764eeb7f5b60c05) > [!WARNING] > > **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. > [!NOTE] > > **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 > [card] [Invoice with Stripe](/integrations/invoice-integrations/stripe) > > Native integration optimized for most billing use cases. > [card] [Invoice with Marketplaces](/integrations/marketplace-integrations/aws) > > Native metering integration to AWS, Azure, and GCP Marketplaces. > [card] [Invoice with NetSuite](/integrations/invoice-integrations/netsuite) > > 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. * **Access type**: Credits and commits can be denominated in either spend or quantity. Use quantity-based credits/commits to denote an allocation like "100 free phone calls included per month". Use spend based credits/commits to encode an enterprise commitment for \$3000, or a \$10 purchase of prepaid AI credits. * **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 or quantity-based amount of free usage. Common scenarios for free credits include free trials, reimbursement for downtime (SLA credits), and promotions. > [!NOTE] > > 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. Select an access type. Use a spend-based credit to give away a monetary amount of free spend -- denoted in either a fiat currency or a custom pricing unit. Use a quantity-based credit to give away units of usage (e.g. 100 tokens or 1000 enrichments). 4. (Optional) Add an internal description to explain why you’re granting the credit. 5. (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 spend-based credits, while only usage charges can consume quantity-based credits. 6. (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. 7. 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: 8. (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). 9. 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, quantity-based credit -- the customer will receive 10 free units of usage in October 2026, November 2026, and December 2026. > [!NOTE] > > For quantity-based credits and commits, do not specify a `credit_type_id` when creating the credit -- instead use the `access_type`: `quantity`. When you fetch information about quantity-based credits and commits in endpoints including `getContract` and `listCustomerBalances`, Metronome will populate a placeholder `credit_type_id` of `00000000-0000-0000-0000-000000000000`. ```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": { "access_type":"quantity", "schedule_items": [ { "amount": 10, "starting_at": "2026-10-01T00:00:00.000Z", "ending_before": "2026-11-01T00:00:00.000Z" }, { "amount": 10, "starting_at": "2026-11-01T00:00:00.000Z", "ending_before": "2026-12-01T00:00:00.000Z" }, { "amount": 10, "starting_at": "2026-12-01T00:00:00.000Z", "ending_before": "2027-01-01T00:00:00.000Z" } ] } }' ``` ## Issue a prepaid or postpaid commit​ Prepaid and postpaid commits represent an agreement by a customer to spend or use an 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. Prepaid commits can include access schedules denoted in fiat currency, custom pricing units, or a quantity of usage. 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. Select an access type - spend-based (default) or quantity-based. 4. (Optional) Add an internal description explaining the reason for granting the commit. 5. (Optional) If the commit 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 spend-based commits, while only usage charges can consume quantity-based commits. 6. 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. 7. (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. 8. 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. 9. (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, spend 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 spend amount, there’s a final true-up invoice on the `invoice_date`. Postpaid commits are only used for monetary commitments in fiat currency. 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 omitted, all usage, subscription, and composite charges can consume spend-based credits/commits, while only usage charges can consume quantity-based credits/commits. 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. > [!NOTE] > > **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. > [!NOTE] > > **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" } } ``` When using quantity-based commits and credits, negative commit application line items are still denoted in spend. You can sum over negative line items to understand the monetary value to customers of quantity-based credits. # 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). > [!NOTE] > > **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). > [!NOTE] > > **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](https://mintcdn.com/metronome-b35a6a36/C_lGxKgdkdHt6xoX/images/docs/pricing-packaging/apply-credits/discounts/add-commit-rate-68340b60850c9b9f13b197158243a07d.png?fit=max\&auto=format\&n=C_lGxKgdkdHt6xoX\&q=85\&s=f10f75d2d94e2e363350be17e334306f) ### 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. > [!WARNING] > > **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] > > **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. > [!NOTE] > > **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 | > [!TIP] > > 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. > [!NOTE] > > **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. > [!NOTE] > > **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 * If using Stripe as the payment provider, ensure the customer has a default payment method specified and a valid stored customer address. Otherwise, payments will fail and commits will not be created. * If using an External payment provider, make sure you have all required information is stored in that system. * **Map the Metronome commit product to the associated Stripe product.** Without this mapping, 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. > [!NOTE] > > **SET TIMESTAMP TO NOW** > > Given payment is attempted immediately, you must set the `invoice_schedule.schedule_items.timestamp` to the time of or before the request. 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/webhooks/webhook-types#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. > [!NOTE] > > **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. > [!NOTE] > > **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. 8. If there are multiple prepaid commits or credits with the same priority, cost basis, product and usage applicability, `ending_before`, `starting_on`, and applicable contracts, burn down is based on the access type of the prepaid commit or credit. Quantity-based credits/commits burn down before spend-based credits/commits. ### 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" ] } ] } ] }' ``` # 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](https://mintcdn.com/metronome-b35a6a36/C_lGxKgdkdHt6xoX/images/docs/pricing-packaging/billing-model-guides/enterprise-commit/enterprise-commit-model-76b33a992199498966431da1792deb93.png?fit=max\&auto=format\&n=C_lGxKgdkdHt6xoX\&q=85\&s=201bef976ae48519b8487a05296aaa44) 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] > > **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. # Implement a free trial Source: https://docs.metronome.com/guides/pricing-packaging/billing-model-guides/free-trials/implement-a-trial Create a trial contract with an expiring credit, wire up alerts and webhooks, convert the customer to paid, and handle the variations you are most likely to need: ending a trial early, a recurring free tier, and a prepaid landing. Read [Free trials](/guides/pricing-packaging/billing-model-guides/free-trials/overview) first and complete its prerequisites, so that your custom-field keys are registered and your system notifications are enabled. ## Set up the trial ### Register custom-field keys (once) Custom fields are how you mark a contract or credit as a trial, so that alerts, webhooks, and reports can tell trials apart from everything else a customer holds. Register each key once per environment before anything references it. ```bash theme={null} for spec in customer:trial_started_at customer:trial_source contract:contract_type contract_credit:trial contract_credit:trial_model; do curl -s -X POST https://api.metronome.com/v1/customFields/addKey \ -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ -d "{\"entity\":\"${spec%%:*}\",\"key\":\"${spec##*:}\",\"enforce_uniqueness\":false}" done ``` ### Create the customer ```bash theme={null} curl -s -X POST https://api.metronome.com/v1/customers \ -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '{ "name": "Acme Corp", "ingest_aliases": ["acme-prod"], "custom_fields": { "trial_started_at": "2026-10-01T15:00:00Z", "trial_source": "self_serve" } }' ``` ### Create the trial contract — expiring credit \$100 of credit, valid 14 days, [scoped](/guides/pricing-packaging/apply-credits-and-commits/target-credit-and-commits) to the products carrying the `Language models` [product tag](/guides/implement-metronome/core-concepts/create-products-contracts), and burned before anything else the customer holds (`priority: 1`). ```bash theme={null} curl -s -X POST https://api.metronome.com/v1/contracts/create \ -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '{ "customer_id": "13117714-3f05-48e5-a6e9-a66093f13b4d", "name": "Trial", "starting_at": "2026-10-01T15:00:00Z", "rate_card_id": "d7abd0cd-4ae9-4db7-8676-e986a4ebd8dc", "uniqueness_key": "trial-13117714-3f05-48e5-a6e9-a66093f13b4d", "custom_fields": { "contract_type": "trial" }, "credits": [{ "name": "Trial credit", "product_id": "609e4cf2-6ea2-4b07-a46c-6596f041b69e", "priority": 1, "applicable_product_tags": ["Language models"], "custom_fields": { "trial": "true", "trial_model": "expiring_credit" }, "access_schedule": { "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "schedule_items": [{ "amount": 10000, "starting_at": "2026-10-01T15:00:00Z", "ending_before": "2026-10-15T15:00:00Z" }] } }] }' ``` To keep trial users out of specific products, add an `overrides[]` entry with `"entitled": false` for those product tags. The trial ends as soon as either limit is reached: the balance hits 0, or the access schedule reaches its `ending_before` date. If any balance is left when the schedule ends, Metronome expires the remainder and records an expiration entry on the credit's ledger. That entry does not affect revenue, unlike the expiration of a prepaid commit — see [revenue recognition](/guides/reporting-insights/financial-reporting/revenue-recognition) for how each is treated. Note that the contract above has no end date, and only the credit is time-bounded. When the credit expires the contract carries on and usage is rated at your list prices, so the customer lands on pay-as-you-go with no further action from you. Create a separate paid contract with a transition when the paid terms differ from the trial contract's, such as a different rate card, a prepaid commit, or a recurring free tier. The [reference architecture](/guides/pricing-packaging/billing-model-guides/free-trials/overview#reference-architecture) covers the trade-off between the two shapes. To build one of the other patterns, start from the request above and change it as follows: * **Skew toward time.** Keep a modest amount and push `ending_before` further out, for products where adoption ramps slowly. Every access-schedule segment requires an `ending_before`, so a credit that never expires isn't possible. * **Effectively unlimited.** Grant far more than a trial customer could plausibly consume and keep the window short. The customer never meets the cap, and you still get balance tracking, alerts, and a complete drawdown record to learn from. * **Quantity-based instead of spend-based.** Denominate the credit in a [custom pricing unit](/guides/pricing-packaging/make-pricing-changes/use-currency-custompricingunits) rather than a currency by setting `credit_type_id` to that unit. The trial then grants an amount of units, such as tokens or requests, instead of dollars. * **Time-only, uncapped.** Remove the `credits` array and add a time-bounded zero multiplier in its place: ```json theme={null} "overrides": [{ "type": "MULTIPLIER", "multiplier": 0, "applicable_product_tags": ["Language models"], "starting_at": "2026-10-01T15:00:00Z", "ending_before": "2026-10-15T15:00:00Z" }] ``` Because there is no credit, this model produces no balance alerts and no `credit.segment.end` event. The override's end date is your only trial-end signal. To limit exposure after the trial, consider a [spend threshold](/guides/customers-billing/optimize-customer-experience/set-customer-spend-control) on the paid contract. * **Reverse trial.** Keep the trial credit as-is, and add a `recurring_credits[]` item to the paid contract you renew into, so conversion lands the customer on a small permanent allowance. See [recurring free tier](#recurring-free-tier). ### Alerts [Threshold alerts](/guides/customers-billing/set-up-notifications/threshold-notifications) are evaluated per customer, so create each one once and leave out `customer_id` to have it apply to everyone. Use [`alert_specifiers`](/guides/customers-billing/set-up-notifications/create-alert-specifiers) to evaluate only trial-tagged credits. Set a `uniqueness_key` so that retrying a request doesn't create a duplicate alert. ```bash theme={null} # Nudge: 25% of trial credit remaining. threshold = percentage REMAINING. curl -s -X POST https://api.metronome.com/v1/alerts/create -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '{ "name": "Trial credit 25% remaining", "alert_type": "low_remaining_contract_credit_percentage_reached", "threshold": 25, "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "evaluate_on_create": false, "uniqueness_key": "trial-pct-25" }' # Nudge: 3 days left on the trial credit segment. Evaluated by a daily cron. curl -s -X POST https://api.metronome.com/v1/alerts/create -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '{ "name": "Trial ends in 3 days", "alert_type": "low_remaining_days_for_contract_credit_segment_reached", "threshold": 3, "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "evaluate_on_create": false, "uniqueness_key": "trial-days-3" }' # Backstop: trial balance exhausted by usage. Scoped to trial credits via alert_specifiers. curl -s -X POST https://api.metronome.com/v1/alerts/create -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '{ "name": "Trial balance zero", "alert_type": "low_remaining_contract_credit_and_commit_balance_reached", "threshold": 0, "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "evaluate_on_create": false, "uniqueness_key": "trial-balance-zero", "alert_specifiers": [{ "custom_field_filters": [{ "entity": "ContractCredit", "key": "trial", "value": "true" }] }] }' ``` A few things to keep in mind when creating these alerts: * `evaluate_on_create: false` skips only the initial evaluation. An alert that applies to all customers still fires for existing ones the next time their state changes. * The days-remaining alert fires as soon as you create it if the trial is shorter than its threshold. * `alert_specifiers` controls which credits are evaluated, but it is not echoed back in the webhook payload. Valid `entity` values are `Contract`, `Commit`, `ContractCredit`, and `ContractCreditOrCommit`. Using `group_key_filter` or per-key grouped specifiers requires account enablement, so contact Metronome support if you need them. ### Handle the webhooks Enable the `credit.segment.start`, `credit.segment.end`, `credit.archive`, and `contract.end` [system notifications](/guides/customers-billing/set-up-notifications/system-notifications) and point them at your webhook endpoint. > [!TIP] > > **Use `credit.segment.end` as the trial-end signal.** It fires at the segment boundary itself rather than after a later evaluation, and it carries credit, contract, and customer custom fields, so your handler needs no follow-up lookup. Example payload: ```json theme={null} { "id": "56a6f43c-1719-56a1-b339-398f072093f0", "type": "credit.segment.end", "timestamp": "2026-10-15T15:00:00Z", "environment_type": "PRODUCTION", "credit_id": "71189e85-f86c-4ec7-a31d-b491d585037a", "credit_custom_fields": { "trial": "true", "trial_model": "expiring_credit" }, "contract_id": "65528c67-fff6-4130-a6fa-115a65223694", "contract_custom_fields": { "contract_type": "trial" }, "parent_recurring_credit_id": null, "segment_index": 0, "segment_count": 1, "segment_id": "9693970e-663f-5457-96cf-2a50f4e14278", "customer_id": "13117714-3f05-48e5-a6e9-a66093f13b4d", "customer_custom_fields": { "trial_started_at": "2026-10-01T15:00:00Z", "trial_source": "self_serve" } } ``` The same event fires for three different reasons: the segment reached its end date, a conversion ended the trial early, or the credit was archived. Use the events that accompany it to tell them apart: ```python theme={null} def on_webhook(evt): if evt["type"] in ("credit.segment.end", "contract.end", "credit.archive"): # Record every event against customer + timestamp, the two fields all three share. record(evt["type"], evt["customer_id"], evt["timestamp"]) if evt["type"] == "credit.segment.end" and evt.get("credit_custom_fields", {}).get("trial") == "true": # contract.end and credit.archive carry the same timestamp but may be delivered # after this one, so classify after a short grace period rather than right now. schedule(classify_trial_end, evt["customer_id"], evt["timestamp"], delay_seconds=60) elif evt["type"] == "alerts.low_remaining_contract_credit_and_commit_balance_reached": # Backstop for USAGE exhaustion only. Every other path to a $0 balance fires this # alert too, so guard twice. Never branch on triggered_by: it names what triggered # the evaluation, not what emptied the balance. cid = evt["properties"]["customer_id"] if trial_already_ended(cid): return # segment.end path already classified it bal = list_balances(cid) # POST /v1/contracts/customerBalances/list trial = next((c for c in bal if c["type"] == "CREDIT" and c["custom_fields"].get("trial") == "true"), None) # Usage is the only path that empties the balance while the segment is still open. if trial and trial["balance"] == 0 and segment_open(trial, at=evt["properties"]["timestamp"]): mark_trial_exhausted(cid, at=evt["properties"]["timestamp"]) elif evt["type"] in ("alerts.low_remaining_contract_credit_percentage_reached", "alerts.low_remaining_days_for_contract_credit_segment_reached"): nudge(evt["properties"]["customer_id"], evt["type"], evt["properties"]) def classify_trial_end(customer_id, timestamp): if recorded("credit.archive", customer_id, timestamp): cause = "archived" elif recorded("contract.end", customer_id, timestamp): cause = "converted_or_ended" else: cause = "expired" mark_trial_ended(customer_id, cause, at=timestamp) def segment_open(credit, at): # Expiry, conversion, and truncation all close the segment before the alert evaluates. return any(i["starting_at"] <= at < i["ending_before"] for i in credit["access_schedule"]["schedule_items"]) ``` Alert payloads for reference: ```json theme={null} { "type": "alerts.low_remaining_contract_credit_and_commit_balance_reached", "properties": { "customer_id": "13117714-3f05-48e5-a6e9-a66093f13b4d", "alert_id": "5a5c0b8e-3f21-4c7d-8b95-1e6a0d24f7b3", "timestamp": "2026-10-08T21:39:25.513Z", "threshold": 0, "alert_name": "Trial balance zero", "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "remaining_balance": 0, "triggered_by": "usage" } } { "type": "alerts.low_remaining_contract_credit_percentage_reached", "properties": { "customer_id": "13117714-3f05-48e5-a6e9-a66093f13b4d", "alert_id": "fafadab6-7c14-4e82-9d35-08b1c6ea5f49", "timestamp": "2026-10-06T21:33:54.577Z", "threshold": 25, "alert_name": "Trial credit 25% remaining", "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "remaining_percentage": 20 } } { "type": "alerts.low_remaining_days_for_contract_credit_segment_reached", "properties": { "customer_id": "13117714-3f05-48e5-a6e9-a66093f13b4d", "alert_id": "937d89a6-6b02-4f51-8a7c-3e94d5b1c082", "credit_id": "71189e85-f86c-4ec7-a31d-b491d585037a", "threshold": 3, "alert_name": "Trial ends in 3 days", "remaining_days": 2.8 } } ``` Unlike the system notifications above, alert payloads do not include custom fields, `contract_id`, or `environment_type`, so look the credit up through the API when you need those. Of the three alerts, only the days-remaining one includes a `credit_id`, and only it has no `timestamp`. `triggered_by` names the evaluation trigger rather than the reason the threshold was crossed, so don't branch on it. ### Convert to paid Create the paid contract with a transition from the trial contract. `starting_at` must be hour-aligned, and it is the instant the trial ends. ```bash theme={null} curl -s -X POST https://api.metronome.com/v1/contracts/create \ -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '{ "customer_id": "13117714-3f05-48e5-a6e9-a66093f13b4d", "name": "Pay as you go", "starting_at": "2026-10-15T15:00:00Z", "rate_card_id": "d7abd0cd-4ae9-4db7-8676-e986a4ebd8dc", "custom_fields": { "contract_type": "paid" }, "transition": { "from_contract_id": "65528c67-fff6-4130-a6fa-115a65223694", "type": "RENEWAL" } }' ``` For a pay-as-you-go landing with a card on file, add a [spend threshold](/guides/customers-billing/optimize-customer-experience/set-customer-spend-control) to the paid contract to control post-trial risk. The transition has these effects: * The trial contract's `ending_before` is set to the paid contract's `starting_at`, leaving no gap and no overlap. * The trial credit is truncated to that instant and any unused balance expires. The ledger records a deduction for consumed usage and an expiration entry for the remainder, both stamped at the transition time. Nothing rolls over unless you set `rollover_fraction`. * Accrued trial usage is re-dated from the billing-period boundary to the transition instant, then invoiced once the grace period ends and the invoice finalizes. * You receive `contract.edit` when the paid contract is created, followed by `credit.segment.end` and `contract.end` at the transition instant. * Both contracts return the same `transitions[]` entry, holding `type`, `from_contract_id`, and `to_contract_id`. It has no timestamp, so read the effective time from `contracts_transitions.date` in Data Export. ### End a trial early You might need to end a trial before its window closes: the customer converts ahead of schedule and you don't want free credit burning alongside paid usage, sales renegotiates the evaluation period, or a trial is being misused and you want to shut off the allowance. The cleanest way to do it is to truncate the credit's access schedule. The credit keeps its ledger, Metronome emits `credit.segment.end`, and the \$0 balance alert fires shortly afterward. Set `ending_before` to an hour boundary at or after the segment's `starting_at`; a zero-length segment is accepted and expires the full balance immediately. ```bash theme={null} curl -s -X POST 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": "65528c67-fff6-4130-a6fa-115a65223694", "update_credits": [{ "credit_id": "71189e85-f86c-4ec7-a31d-b491d585037a", "access_schedule": { "update_schedule_items": [{ "id": "b3d7e912-5c48-4a6f-9e21-7fa0c85d3b64", "ending_before": "2026-10-03T14:00:00Z" }] } }] }' ``` Note that `update_credits[]` identifies the credit with `credit_id` while the nested schedule item uses `id`. Both values come from `POST /v1/contracts/customerBalances/list`. > [!WARNING] > > **Avoid archiving a trial credit.** Archiving zeroes the balance and deletes the credit's ledger from both the API and Data Export, hides the credit unless you pass `include_archived: true`, and leaves it out of the in-app Commits and credits report. You are left with a grant that has no consumption history to reconcile against. Reserve archiving for cleanup where you want the grant to disappear entirely. ### Recurring free tier A recurring credit grants an allowance that refreshes every period, which suits both a permanent free tier and the landing state of a reverse trial. This example grants \$10 of usage a month on a perpetual contract, with no rollover. `recurrence_frequency` is an enum string, and recurring credits do not accept `custom_fields`. ```bash theme={null} curl -s -X POST https://api.metronome.com/v1/contracts/create \ -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '{ "customer_id": "13117714-3f05-48e5-a6e9-a66093f13b4d", "name": "Free tier", "starting_at": "2026-10-15T15:00:00Z", "rate_card_id": "d7abd0cd-4ae9-4db7-8676-e986a4ebd8dc", "custom_fields": { "contract_type": "free_tier" }, "transition": { "from_contract_id": "65528c67-fff6-4130-a6fa-115a65223694", "type": "RENEWAL" }, "recurring_credits": [{ "name": "Monthly free allowance", "product_id": "609e4cf2-6ea2-4b07-a46c-6596f041b69e", "priority": 1, "access_amount": { "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "unit_price": 1000, "quantity": 1 }, "commit_duration": { "unit": "PERIODS", "value": 1 }, "recurrence_frequency": "MONTHLY", "proration": "NONE", "rollover_fraction": 0, "starting_at": "2026-10-15T15:00:00Z", "applicable_product_tags": ["Language models"] }] }' ``` Metronome pre-generates two child credit segments, and the upcoming one contributes nothing to the balance until its period begins. Each child carries a `recurring_credit_id`, which webhook payloads call `parent_recurring_credit_id`. Setting `recurrence_frequency` explicitly anchors each period to the credit's own `starting_at`, which means a period can reset partway through a billing period. Omit it to follow the contract's usage statement schedule instead. Alerts mean something different on this model. A \$0 or percentage-remaining alert now tells you that this period's allowance is used up, which is a monthly throttling signal rather than the end of a trial, so keep a separate alert configuration for each model. ### Prepaid landing with a payment gate For a "buy \$20 before you continue" conversion, add a [payment-gated prepaid commit](/guides/pricing-packaging/apply-credits-and-commits/manual-payment-gated-commits) to the paid contract. Metronome creates the invoice immediately and releases the commit once payment succeeds. See that guide for the billing-provider setup and the rest of the requirements. ```bash theme={null} curl -s -X POST 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": "8f2a1c64-9b7e-4d18-a5c3-6e0f2b9d4a71", "add_commits": [{ "type": "PREPAID", "name": "Prepaid balance", "product_id": "3f6c8ad1-2e54-4b79-9c08-5d1ea7b46f23", "priority": 100, "access_schedule": { "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "schedule_items": [{ "amount": 2000, "starting_at": "2026-10-15T15:00:00Z", "ending_before": "2027-10-15T15:00:00Z" }] }, "invoice_schedule": { "credit_type_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "schedule_items": [{ "amount": 2000, "timestamp": "2026-10-15T15:00:00Z" }] }, "payment_gate_config": { "payment_gate_type": "STRIPE", "tax_type": "STRIPE" } }] }' ``` For auto-recharge once the customer is paying, add a [prepaid balance threshold](/guides/customers-billing/optimize-customer-experience/prepaid-balance-thresholds) to the contract. ## Behavior reference ### How each trial-end path shows up | Path to zero balance | `credit.segment.end` | `contract.end` | `$0` balance alert | Ledger (API literal) | | - | - | - | - | - | | Usage exhaustion | no (segment still open) | no | **fires**, `triggered_by: usage` | `CREDIT_AUTOMATED_INVOICE_DEDUCTION` | | Natural expiry (`ending_before`) | **fires at the boundary** | no (contract stays open) | **does not fire** | `CREDIT_EXPIRATION` | | Conversion to a paid contract | fires at transition instant | fires | fires later, once the trial invoice finalizes | deduction + `CREDIT_EXPIRATION` at transition time | | `/v2/contracts/edit` truncation | fires | no | fires, no `triggered_by` | `CREDIT_EXPIRATION` | | `credits/archive` | fires | no | fires, no `triggered_by` | **ledger deleted** | The \$0 balance alert is a usage signal. [Threshold notifications](/guides/customers-billing/set-up-notifications/threshold-notifications) are evaluated when usage is ingested and when customer metadata changes, so a credit that reaches its end date with unused balance does not produce one. Use `credit.segment.end` to detect a trial that ends on schedule, and keep the \$0 alert for trials exhausted by usage. ### Payload differences between the two notification families | | [System notifications](/guides/customers-billing/set-up-notifications/system-notifications) (`credit.*`, `contract.*`) | [Threshold notifications](/guides/customers-billing/set-up-notifications/threshold-notifications) (`alerts.*`) | | - | - | - | | Fields live under | the top level | `properties` | | `environment_type` | yes | no | | Custom fields | credit, contract, and customer | none | | Object ids | `credit_id`, `contract_id`, `segment_id` | `customer_id`, plus `credit_id` on days-remaining | | Timestamp | the object's configured time | the evaluation time, and absent on days-remaining | ### Things that are easy to get backwards * The percentage alert's `threshold` is the percentage **remaining**, so a threshold of 25 fires when 25% is left. * Ledger entry types are named differently in each surface: `CREDIT_EXPIRATION` in the API is `credit_segment_expiration` in Data Export and in-app reports. See the [database reference](/guides/reporting-insights/data-export/database-reference) for the full mapping. * Usage drawdown appears as a single deduction entry per invoice, dated at the end of the service period and rewritten in place, so don't use the ledger to date individual usage. * An invoice's `issued_at` is its nominal date, while finalization happens after the [grace period](/guides/implement-metronome/core-concepts/how-invoicing-works). # Free trials Source: https://docs.metronome.com/guides/pricing-packaging/billing-model-guides/free-trials/overview Choose a free-trial model for a usage-based product, implement it on Metronome contracts, and measure conversion and attrition. > [card] [Implement a free trial](/guides/pricing-packaging/billing-model-guides/free-trials/implement-a-trial) > > Step-by-step API calls: custom fields, trial contract, alerts, webhooks, conversion, early end, recurring free tier, prepaid landing. > [card] [Trial data reference](/guides/pricing-packaging/billing-model-guides/free-trials/trial-data-reference) > > Metric definitions, Data Export SQL, and in-app reports for trial starts, conversion, attrition, and retention. ## Why offer a trial Two reasons come up most often with usage-based products: * **Adoption.** A trial lowers the barrier to a first integration, which matters most when you are launching a usage-based product for the first time or moving customers over from a subscription. * **Pricing insight.** You cannot price usage well until you know what usage looks like. A trial produces real consumption data — which metrics move, how quickly, and how much they vary between customers — early enough to shape your rate card. Metering trial usage exactly as you meter paid usage is what makes that data worth having. ## Choosing a trial model Trials are bounded in two ways: by **spend**, using an allowance the customer draws down, and by **time**, using a window that closes. Almost nobody picks only one. Setting both is the market norm and the safer default, because each bound covers the case the other misses: a spend cap alone leaves a customer sitting on an allowance indefinitely, and a time cap alone leaves your costs open-ended. The interesting decision is which way you skew. A large allowance over a short window suits a fast, intensive evaluation. A smaller allowance over a long window suits products where adoption ramps slowly and the customer needs weeks to integrate. In Metronome, a credit with an access schedule bounds both at once, because the schedule carries an amount and an `ending_before`. A zero-price override bounds time alone. This page covers how to choose between them, and how to set up your account so a trial can be converted and measured cleanly. ### Common trial patterns Looking at a survey of the market, a handful of patterns appear. Only a few examples actually mean "free trial"; the others are worth knowing because your customers will ask for them and each maps to a different Metronome construct. The `trial_model` column is the value to record on the credit, per [tagging and conventions](#tagging-and-conventions); it is `n/a` for the patterns with no trial credit to tag. | Pattern | What the customer gets | Metronome construct | `trial_model` | | - | - | - | - | | **Expiring credit** (amount **and** time) | e.g. \$400 for 30 days, whichever ends first | Credit with one access-schedule segment (capped trial) | `expiring_credit` | | **Time-boxed, uncapped** | Unlimited usage for N days | Price override `multiplier: 0`, time-bounded (uncapped trial) | `time_only` | | **Amount-only free credit** (no meaningful expiry) | \$X, use it whenever | Credit with a long-dated segment (every credit segment requires `ending_before`) | `amount_only` | | **Reverse trial** | Generous trial, then fall back to a small free tier | Trial credit + recurring credit, or trial contract → free-tier contract | `reverse` | | **Recurring free tier** | N units or \$X **per month**, forever | `recurring_credits[]` on a perpetual contract | n/a | | **No trial, prepaid minimum** | Buy \$5 of credit before the first call | [Prepaid commit with a payment gate](/guides/pricing-packaging/apply-credits-and-commits/manual-payment-gated-commits), optionally with [auto-recharge](/guides/customers-billing/optimize-customer-experience/prepaid-balance-thresholds) | n/a | ### Choosing between them These are the drivers worth weighing: | Driver | Pushes toward | Why | | - | - | - | | **Cost to serve a free user** (GPU inference, compute, egress) | Amount cap; smaller grants | Time alone doesn't bound cost, and unmetered free access has generally proven expensive to sustain | | **Fraud exposure** (freejacking, denial-of-wallet, spam) | Amount cap + product-side identity controls; card-on-file for high-COGS products | An amount cap bounds the worst case; identity controls and prepayment reduce how often it happens | | **Time-to-value** | Fast TTV → small expiring credit; slow TTV (migrations, integrations) → longer window or reverse trial | The customer must reach the "aha" before the cap | | **Sales motion** | Sales-assisted → longer/larger, with alerts routed to reps; self-serve → tight, automated | Trial signals become lead-qualification signals | | **What you can measure** | Patterns with a clean end state (expiring credit; conversion to a paid contract) | Attrition and conversion reporting needs unambiguous events — see the [data reference](/guides/pricing-packaging/billing-model-guides/free-trials/trial-data-reference) | ### Recommendation * **Default: expiring credit** (amount + time), converted to a paid contract. It bounds cost, produces clean end states, and is what customers already understand. * **A deliberately oversized credit** when you want the trial to feel unlimited. Grant far more than a trial customer could plausibly consume, keep the window short, and the customer never meets the cap while you still get balance tracking, alerts, and a full drawdown record. This is a common choice when you are new to usage-based pricing and want to watch real consumption before committing to a rate card. * **Time-only override** when per-unit COGS are low or adoption of a platform takes serious ramping and you want the customer to experience the whole product. This model produces no balance signals, so the schedule end is your only trial-end event. Prefer the oversized credit above if you want that same experience with visibility into spend. * **Recurring free tier** for a permanent low-cost tier or as the landing state of a reverse trial. Note that its alerts mean something different, since a drained balance signals a throttled month rather than the end of a trial (see [recurring free tier](/guides/pricing-packaging/billing-model-guides/free-trials/implement-a-trial#recurring-free-tier)). * **Prepaid minimum** as the *conversion landing state*, not as the trial. ## Reference architecture ### Trial contract → paid contract Model the trial as **its own contract** and convert by creating the paid contract with `transition: { type: "RENEWAL", from_contract_id }` (see [contract lifecycle transitions](/guides/customers-billing/manage-customers/manage-customer-lifecycle)). This is preferred over a single perpetual contract because: * The trial package and the paid package evolve independently (different rate cards, credits, commits, subscriptions). * Conversion is a first-class row in `contracts_transitions` (Data Export) and `transitioned_from/to_contract_id` (in-app report), so conversion and attrition reporting is a join, not an inference. * The transition end-dates the trial contract at the paid contract's `starting_at`, truncates the trial credit to that instant, and expires any unused balance — no rollover, no dangling credit. ``` customer ──► trial contract (contract_type=trial) └─ credit "Trial credit" {trial=true, trial_model=expiring_credit}, priority 1 │ ├─ credit.segment.end ─────────────► your app: trial ended (expiry | conversion | archive) ├─ % remaining alert / days-left alert ► nudges └─ $0 balance alert ──────────────────► backstop only │ POST /v1/contracts/create {transition: RENEWAL} ▼ paid contract (contract_type=paid): PAYG, or prepaid commit + payment gate, or recurring free tier ``` ### Tagging and conventions Every business models trials a little differently, so there is no single trial report that fits all of them. The queries and reports in the [data reference](/guides/pricing-packaging/billing-model-guides/free-trials/trial-data-reference) assume the names and custom fields below. Adopt them and those queries work unchanged; use your own instead and you will need to adjust each query to match. | Object | Field | Value | | - | - | - | | Customer | `custom_fields.trial_started_at`, `custom_fields.trial_source` | ISO timestamp; `self_serve` / `sales` / … | | Trial contract | `name`; `custom_fields.contract_type` | `Trial`; `trial` | | Paid contract | `custom_fields.contract_type` | `paid` | | Trial credit | `name`; `custom_fields.trial`, `custom_fields.trial_model` | `Trial credit`; `"true"`, and the `trial_model` value for your pattern from [common trial patterns](#common-trial-patterns) | | Contract create | `uniqueness_key` | `trial-{customer_id}` — guarantees one trial per customer (409 on retry) | | Conversion | `transition.type` | `RENEWAL` | Tagging earns its keep beyond reporting. Because `trial` and `trial_model` sit on the credit itself, you can point [alert specifiers](/guides/customers-billing/set-up-notifications/create-alert-specifiers) at those fields and alert on trial balances separately from every other credit and commit a customer holds. If you run more than one trial model, that also lets you give each model its own thresholds rather than sharing a single alert. > [!NOTE] > > **Recurring credits cannot carry `custom_fields`.** Identify a recurring free tier by `recurring_credit_id` (API) / `parent_recurring_credit_id` (webhooks), the contract's `contract_type`, the credit `name`, or `applicable_product_tags`. ### Prerequisites and constraints 1. **[Register custom-field keys](/api-reference/custom-fields) first.** Any request that sets an unregistered key fails with `Invalid custom field keys: …`. Entities: `customer`, `contract`, `contract_credit`. 2. **Timestamps are hour-aligned.** Contract `starting_at` and credit `ending_before` must be on an hour boundary (`… is required to be on an hour boundary (e.g. 1:00, not 1:30)`). UTC midnight is *not* required. 3. **Enable the system notifications you need.** Turn on `credit.segment.start`, `credit.segment.end`, `credit.archive`, and `contract.end` from the UI or the API — see [system notifications](/guides/customers-billing/set-up-notifications/system-notifications). ## Next steps > [card] [Implement a free trial](/guides/pricing-packaging/billing-model-guides/free-trials/implement-a-trial) > [card] [Trial data reference](/guides/pricing-packaging/billing-model-guides/free-trials/trial-data-reference) # Trial data reference Source: https://docs.metronome.com/guides/pricing-packaging/billing-model-guides/free-trials/trial-data-reference Metric definitions, queries, and reports for trial starts, conversion, attrition, and retention. Measure your trials with [Data Export](/guides/reporting-insights/data-export/overview) SQL or, without SQL, with [in-app reports](/guides/reporting-insights/in-app-reporting). Both assume the [tagging and conventions](/guides/pricing-packaging/billing-model-guides/free-trials/overview#tagging-and-conventions) from the overview. ## Definitions | Metric | Definition | | - | - | | Trial starts | Contracts whose `contract_type` custom field is `trial`, counted by `starting_at` | | Conversions | `contracts_transitions` rows whose `from_contract_id` is a trial contract, where **`date`** is the effective conversion time | | Conversion rate (cohort) | Conversions within N days ÷ trial starts, by trial-start week or month | | Time to convert | `transition.date − trial.starting_at` | | Exhausted | Trial credit with `balance = 0` and no expiration entry with a negative amount | | Expired unused (attrition) | Trial credit whose ledger has a `credit_segment_expiration` entry with a negative amount, **and** no transition from that contract | | Active trials on day D | Trial contracts with `starting_at ≤ D < coalesce(ending_before, ∞)` and no transition before D | | Post-conversion retention | Converted customers with a finalized invoice where `total > 0` in month M after the conversion month | ## Data Export SQL > [!WARNING] > > **Filter `environment_type` in every query.** Sandbox and production data share a single export destination, so scope each query to `environment_type = 'PRODUCTION'`. Notes that apply to every query: * Contract, balance, and transition tables are **daily snapshots** (`snapshot_id`, `updated_at` = export time), so keep only the most recently exported row per id. Customer, alert, and invoice tables are incremental. See [data availability](/guides/reporting-insights/data-export/overview#data-availability) for the transfer frequency and freshness of each table. * JSON columns export as **strings**: use `json_extract_scalar` (Trino/Athena), `JSON_VALUE` (BigQuery), or `PARSE_JSON(...):path::string` (Snowflake). * Custom fields live under **`metadata.custom_fields`**, not a `custom_fields` column (except `customer.custom_fields`, which is a real column). * Table and column names follow the [database reference](/guides/reporting-insights/data-export/database-reference); a modelled warehouse layer on top may rename or split schemas. More query patterns are in the [SQL cookbook](/guides/reporting-insights/data-export/cookbook). ```sql theme={null} -- One current row per contract / balance / transition (snapshot tables): latest export wins WITH contracts AS ( SELECT id, customer_id, name, starting_at, ending_before, archived_at, created_at, json_extract_scalar(metadata, '$.custom_fields.contract_type') AS contract_type FROM (SELECT c.*, row_number() OVER (PARTITION BY c.id ORDER BY c.updated_at DESC) AS rn FROM contracts_contracts c WHERE c.environment_type = 'PRODUCTION') WHERE rn = 1 ), trials AS (SELECT * FROM contracts WHERE contract_type = 'trial'), conversions AS ( SELECT t.from_contract_id AS trial_contract_id, t.to_contract_id AS paid_contract_id, t.date AS converted_at FROM (SELECT t.*, row_number() OVER (PARTITION BY t.id ORDER BY t.updated_at DESC) AS rn FROM contracts_transitions t WHERE t.environment_type = 'PRODUCTION') t JOIN trials tr ON tr.id = t.from_contract_id WHERE t.rn = 1 AND upper(t.type) = 'RENEWAL' ), -- Trial credits with their expiration entries (ledger is a JSON array string) trial_credits AS ( SELECT b.id AS credit_id, b.contract_id, b.customer_id, b.balance, json_extract_scalar(b.access_schedule, '$.schedule_items[0].date') AS segment_start, json_extract_scalar(b.access_schedule, '$.schedule_items[0].end_date') AS segment_end, b.ledger FROM (SELECT b.*, row_number() OVER (PARTITION BY b.id ORDER BY b.updated_at DESC) AS rn FROM contracts_balances b WHERE b.environment_type = 'PRODUCTION') b WHERE b.rn = 1 AND b.type = 'credit' AND json_extract_scalar(b.metadata, '$.custom_fields.trial') = 'true' ), expirations AS ( SELECT tc.credit_id, tc.contract_id, CAST(json_extract_scalar(e, '$.amount') AS double) AS expired_amount, -- negative in the export from_iso8601_timestamp(json_extract_scalar(e, '$.timestamp')) AS expired_at FROM trial_credits tc CROSS JOIN UNNEST(CAST(json_parse(tc.ledger) AS ARRAY(JSON))) AS u(e) WHERE json_extract_scalar(e, '$.type') = 'credit_segment_expiration' ), -- Daily trial funnel: starts, conversions, expired-unused (attrition). -- Aggregate each metric on its own date, then join. Conversions and expirations land days -- after the start, so a day spine built only from starting_at would drop most of them. starts_by_day AS ( SELECT date(starting_at) AS day, count(DISTINCT id) AS n FROM trials GROUP BY 1 ), conversions_by_day AS ( SELECT date(converted_at) AS day, count(DISTINCT trial_contract_id) AS n FROM conversions GROUP BY 1 ), expired_unused_by_day AS ( SELECT date(ex.expired_at) AS day, count(DISTINCT ex.contract_id) AS n FROM expirations ex LEFT JOIN conversions cv ON cv.trial_contract_id = ex.contract_id WHERE cv.trial_contract_id IS NULL AND ex.expired_amount < 0 GROUP BY 1 ), days AS ( SELECT day FROM starts_by_day UNION SELECT day FROM conversions_by_day UNION SELECT day FROM expired_unused_by_day ) SELECT d.day, coalesce(s.n, 0) AS trial_starts, coalesce(c.n, 0) AS conversions, coalesce(e.n, 0) AS expired_unused FROM days d LEFT JOIN starts_by_day s ON s.day = d.day LEFT JOIN conversions_by_day c ON c.day = d.day LEFT JOIN expired_unused_by_day e ON e.day = d.day ORDER BY d.day; ``` ```sql theme={null} -- Cohort conversion rate and time-to-convert (trial start month) SELECT date_trunc('month', tr.starting_at) AS cohort, count(*) AS trials, count(cv.trial_contract_id) AS converted, round(100.0 * count(cv.trial_contract_id) / count(*), 1) AS conversion_pct, approx_percentile(date_diff('hour', tr.starting_at, cv.converted_at) / 24.0, 0.5) AS median_days_to_convert FROM trials tr LEFT JOIN conversions cv ON cv.trial_contract_id = tr.id GROUP BY 1 ORDER BY 1; ``` ```sql theme={null} -- Post-conversion retention: months with a paid invoice, by conversion cohort SELECT date_trunc('month', cv.converted_at) AS cohort, date_diff('month', date_trunc('month', cv.converted_at), date_trunc('month', i.start_timestamp)) AS month_n, count(DISTINCT i.customer_id) AS paying_customers FROM conversions cv JOIN contracts pc ON pc.id = cv.paid_contract_id JOIN invoice i ON i.customer_id = pc.customer_id AND i.status = 'FINALIZED' AND i.total > 0 AND i.environment_type = 'PRODUCTION' AND i.start_timestamp >= cv.converted_at GROUP BY 1, 2 ORDER BY 1, 2; ``` (Retention here means "billed for usage in month N"; for usage-based retention independent of billing, use `line_item.quantity` by `product_id` instead.) ## Without Data Export Data Export is an add-on. These [in-app reports](/guides/reporting-insights/in-app-reporting) cover the essentials: | Need | Report | What to read | | - | - | - | | Trial expirations with all tags | **Commit expiration ledger entries by month** | `revenue_category = credit_segment_expiration`; `ledger_entry_amount`, which is **positive** here and negative in the API and export; `customer_custom_fields`, `contract_metadata`, `balances_metadata` | | Conversions | **Contracts by created date** | `transitioned_from_contract_id` / `transitioned_to_contract_id`, flattened onto each contract row; `metadata` holds `contract_type` | | Trial grants | **Commits and credits by created date** | One row per credit, plus `metadata`; archived credits are excluded | | Paid activity | **Invoices by status and effective date** | Finalized invoices only, with `finalized_at`; `metadata` carries contract and customer custom fields | For real-time per-customer state, `POST /v1/contracts/customerBalances/list` returns the credit with `custom_fields`, `access_schedule`, `ledger`, and `balance`. # 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 > [card] [Pay-as-you-go Billing](/guides/pricing-packaging/billing-model-guides/pay-as-you-go) > [card] [Enterprise Commits](/guides/pricing-packaging/billing-model-guides/enterprise-commit) > [card] [Subscriptions w/ Usage](/guides/pricing-packaging/billing-model-guides/hybrid-business-models) > [card] [Pre-Paid Credits](/guides/pricing-packaging/billing-model-guides/prepaid-credits) # 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. > [!NOTE] > > **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](https://mintcdn.com/metronome-b35a6a36/C_lGxKgdkdHt6xoX/images/docs/pricing-packaging/billing-model-guides/hybrid-business/hybrid-model-229fb93b63564f29cdebe36b183a6d63.png?fit=max\&auto=format\&n=C_lGxKgdkdHt6xoX\&q=85\&s=3201a981d90d5852bd0c25d12c852b71) ### 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](https://mintcdn.com/metronome-b35a6a36/C_lGxKgdkdHt6xoX/images/docs/pricing-packaging/billing-model-guides/pay-go/autosales_rate_card-9727f228131ea293ba69270e314f47be.png?fit=max\&auto=format\&n=C_lGxKgdkdHt6xoX\&q=85\&s=cb80644065a84799c1b8bb637961745b) ## 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](https://mintcdn.com/metronome-b35a6a36/C_lGxKgdkdHt6xoX/images/docs/pricing-packaging/billing-model-guides/prepaid-credits/prepaid-credits-model-edc8c2b037014f4ee95500d904c76eed.png?fit=max\&auto=format\&n=C_lGxKgdkdHt6xoX\&q=85\&s=415b15a7888f704436d94b5aa9a67a3a) ### 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/webhooks/best-practices) 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] > > **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](https://mintcdn.com/metronome-b35a6a36/C_lGxKgdkdHt6xoX/images/docs/pricing-packaging/billing-model-guides/prepaid-credits/commit-tracking-ad8d69832510b0565b8fea1ce51e8d97.png?fit=max\&auto=format\&n=C_lGxKgdkdHt6xoX\&q=85\&s=a19d8d057d11c6e01adc5f8e6d5e0c1a) 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). # Billing for provisioned throughput Source: https://docs.metronome.com/guides/pricing-packaging/billing-model-guides/provisioned-throughput Use provisioned-throughput billing when your customers reserve a fixed amount of capacity for a defined period and pay for usage above that commitment. This model is common for compute, data processing, and infrastructure products where a customer needs guaranteed capacity but can also consume additional capacity on demand. In Metronome you can model the reservation as a contract-level Named Schedule, charge for it using a subscription fee, and calculate on-demand overages from usage at each reporting interval using SQL billable metrics that reference the reserved amount encoded on Named Schedules. ## In this guide * Understand provisioned-throughput billing * Learn how Metronome models reservations and calculates overages * Configure SQL billable metrics, products, rates, Named Schedules, and usage events * Show the resulting invoice and invoice breakdowns ## What is provisioned throughput? A provisioned-throughput contract has two commercial components: 1. **Reservation fee:** A recurring fee for a fixed amount of capacity, whether or not the customer consumes all of it. 2. **On-demand overage:** A usage-based charge for capacity consumed above the reservation. For example, a customer might reserve 120 H100 GPUs for a month and pay a fixed monthly fee. If they use 200 H100 GPUs during a 60-second interval, 120 GPUs are covered by the reservation and the remaining 80 GPUs are billed at the on-demand rate. The reservation fee is independent of actual consumption. Customers pay for the committed capacity, then pay the on-demand rate only when their consumption exceeds that commitment. ## How Metronome models provisioned throughput The key components to modeling this business model in Metronome are as follows: | Component | Role in the model | | - | - | | Usage events | Report the customer's actual active capacity at a consistent interval. Events do not need to identify whether capacity is reserved or on demand. | | Named Schedule | Stores the contract's reserved capacity and the period when that value applies. | | SQL billable metrics | Read raw usage and the reservation active at each event timestamp to calculate covered and on-demand quantities. | | Products and rate cards | Attach pricing to reservations and overages. | | Contract | Holds the customer-specific reservation, negotiated rates, and other commercial terms. | SQL billable metrics serve as the bridge between actual usage and reserved amounts encoded as contract terms. They read the reservation amount that was active at each usage interval to determine whether the customer is using under or over their reserved capacity. For this model, you can configure two SQL billable metrics that effectively calculate: | Metric | Calculation | Used by | | - | - | - | | Reserved usage | `min(total_usage, reservation)` | A \$0 reserved-usage product that shows how much consumption was covered by the commitment. The actual reservation fee is charged separately. | | On-demand usage | `max(0, total_usage - reservation)` | A paid usage product that bills capacity above the commitment. | Follow the steps below to configure this model. ## 1. Create the SQL billable metrics Define the SQL billable metrics first so they are available to attach when you create the products in the next step. For each SKU and usage interval, the metrics should: 1. Aggregate raw usage at the scope where the reservation applies. 2. Look up the scheduled reservation active at the same timestamp. 3. Calculate covered usage and on-demand usage separately. ```text theme={null} covered_usage = min(total_usage, reservation) on_demand_usage = max(0, total_usage - reservation) ``` The example queries below reference a `reserved-instance` Named Schedule keyed by `sku`. You create that schedule on the customer's contract in [Step 3](#3-add-the-named-schedule); the metric definitions do not depend on the schedule existing yet. ### Choose the right schedule lookup SQL billable metrics offer two functions for looking up Named Schedule values. | Function | Property matching | Return value | When to use it | | - | - | - | - | | `scheduleValue(name, properties, ts)` | **Exact match.** The name and properties on the schedule must exactly match the lookup. | The value of one active schedule, or `null` when no exact match exists. | A single authoritative value should apply at a timestamp, such as one reservation per SKU. | | `scheduleSum(name, properties, ts)` | **Superset match.** A schedule can include all lookup properties plus additional properties. | The sum of all active matching schedules, or `0` when there are no matches. | Multiple values should intentionally accumulate under the commercial model. | ### Create the on-demand SQL billable metric The following metric aggregates all H100 events into 60-second SKU totals, reads the active H100 reservation, and calculates the on-demand quantity. ```sql theme={null} SELECT SUM( GREATEST( 0, gpu_count - COALESCE( scheduleValue('reserved-instance', { sku: sku }, ts), 0 ) ) ) * 60 AS on_demand_gpu_seconds, sku FROM ( SELECT SUM(properties.gpu_count) AS gpu_count, properties.sku AS sku, DATE_TRUNC('60s', timestamp) AS ts FROM events WHERE event_type = 'gpu_usage' GROUP BY sku, ts ) GROUP BY sku ``` The inner query aggregates all usage events for a SKU into a single 60-second value. For each aggregated row, the outer query looks up the reservation whose schedule properties match that row's SKU and whose segment is active at that timestamp. It subtracts the reservation from aggregated usage and floors the result at zero. When no reservation schedule matches, the example SQL treats the reservation as zero through `COALESCE(..., 0)`. In that case, all usage is billed as on demand. The query multiplies each 60-second result by 60, so the output is in GPU-seconds. Configure the associated product's quantity conversion to divide by 3,600 before applying a GPU-hour rate. ### Create the reserved-usage SQL billable metric To show the portion of usage covered by the reservation, use the same event aggregation and schedule lookup, but use `MIN()` instead of subtracting the reservation: ```sql theme={null} SUM( MIN( gpu_count, COALESCE(scheduleValue('reserved-instance', { sku: sku }, ts), 0) ) ) * 60 AS reserved_gpu_seconds ``` Map this metric to the reserved-usage product, which is normally priced at \$0. This gives customers visibility into the consumption covered by their commitment without charging twice for that capacity. ## 2. Create the products, rate card, and contract Create products for the two calculated usage quantities and the fixed reservation fee, then bundle them on a rate card and attach that rate card to the customer's contract. | Product | Metric or charge | Pricing behavior | | - | - | - | | GPU Usage — Reserved | Reserved-usage SQL billable metric | Usage-based product priced at \$0 per GPU-hour. | | GPU Usage — On-Demand | On-demand SQL billable metric | Usage-based product priced at the contracted on-demand GPU-hour rate. | | Reservation Fee | Subscription charge | Recurring fixed fee for the customer's reserved capacity. | Add all three products to the rate card, then create the customer's contract using that rate card. You can override the on-demand rate and reservation fee on an individual contract to reflect the customer's negotiated commercial terms. > [!NOTE] > > **Example:** Acme's contract charges a \$100,000 monthly reservation fee for 120 H100 GPUs and \$2.00 per GPU-hour for on-demand usage. The reserved-usage product remains at \$0 per GPU-hour because the reservation fee already covers that capacity. ## 3. Add the Named Schedule With the contract in place, add the Named Schedule that stores the customer's reserved capacity. The SQL billable metrics created in Step 1 read from this schedule at billing time. ### What is a Named Schedule? A Named Schedule attaches a time-varying value to a contract. Use it when a contract term, such as a customer's reserved capacity, can change over time. Each schedule is identified within a contract by its **schedule name** and **properties**: * The schedule name describes the kind of value, such as `reserved-instance`. * Properties scope that value, such as `{ "sku": "gpu-H100" }`. The same schedule name with different properties represents a different schedule. For example, a contract can have separate `reserved-instance` schedules for `gpu-H100` and `gpu-A100`. Each schedule has one or more time-bounded segments. A segment provides the value that is active from `starting_at` until the next segment starts or `ending_before` is reached. | Schedule name | Properties | Active from | Active until | Value | | - | - | - | - | - | | `reserved-instance` | `{ "sku": "gpu-H100" }` | January 1, 2026 | June 15, 2026 | 120 GPUs | | `reserved-instance` | `{ "sku": "gpu-H100" }` | June 15, 2026 | December 31, 2026 | 200 GPUs | A Named Schedule does not affect billing by itself. The SQL billable metrics read the value active at the usage timestamp and use it in the billing calculation. ### Create a reservation using a Named Schedule Create a reservation schedule for 120 H100 GPUs on the customer's contract: ```bash theme={null} curl --request POST \ --url https://api.metronome.com/v1/contracts/updateNamedSchedule \ --header 'Authorization: Bearer $METRONOME_API_KEY' \ --header 'Content-Type: application/json' \ --data ' { "customer_id": "$CUSTOMER_ID", "contract_id": "$CONTRACT_ID", "schedule_name": "reserved-instance", "properties": { "sku": "gpu-H100" }, "starting_at": "2026-01-01T00:00:00Z", "ending_before": "2027-01-01T00:00:00Z", "value": 120 } ' ``` ### Change a reservation without changing history When the customer changes their commitment, add a new segment with the same schedule name and properties. For example, increase Acme's H100 reservation to 200 GPUs beginning June 15: ```bash theme={null} curl --request POST \ --url https://api.metronome.com/v1/contracts/updateNamedSchedule \ --header 'Authorization: Bearer $METRONOME_API_KEY' \ --header 'Content-Type: application/json' \ --data ' { "customer_id": "$CUSTOMER_ID", "contract_id": "$CONTRACT_ID", "schedule_name": "reserved-instance", "properties": { "sku": "gpu-H100" }, "starting_at": "2026-06-15T00:00:00Z", "ending_before": "2027-01-01T00:00:00Z", "value": 200 } ' ``` The contract retains the 120-GPU reservation before June 15 and applies the 200-GPU reservation afterward. Historical usage events remain unchanged, and the metric uses the segment that was active at the time of each event. ## 4. Send capacity usage events Send immutable heartbeat events at a consistent interval for each SKU and the dimensions needed to aggregate usage. This example reports active H100 GPUs for a cluster every 60 seconds: ```bash theme={null} curl --request POST \ --url https://api.metronome.com/v1/ingest \ --header 'Authorization: Bearer $METRONOME_API_KEY' \ --header 'Content-Type: application/json' \ --data ' [ { "transaction_id": "2026-01-05T10:05:00Z_cluster_2_gpu-H100", "customer_id": "$CUSTOMER_ID", "timestamp": "2026-01-05T10:05:00Z", "event_type": "gpu_usage", "properties": { "cluster": "cluster_2", "sku": "gpu-H100", "gpu_count": 50 } } ] ' ``` The event reports actual consumption only. It does not label the 50 GPUs as reserved or on demand. Metronome calculates that classification from the customer's contract using the SQL billable metrics and Named Schedule configured in the previous steps. ## 5. Show billing outcomes Suppose Acme uses 200 H100 GPUs during a 60-second interval while its active reservation is 120 GPUs: | Step | GPU count | | - | - | | Usage across all clusters | 200 | | Usage covered by the reservation | 120 | | On-demand overage | 80 | For that interval, Metronome records: * 7,200 covered GPU-seconds: `120 GPUs × 60 seconds` * 4,800 on-demand GPU-seconds: `80 GPUs × 60 seconds` The reserved-usage SQL billable metric reports the covered quantity, while the on-demand SQL billable metric reports the overage quantity. The associated products then convert GPU-seconds to GPU-hours by dividing by 3,600 before applying the applicable rate. For an illustrative monthly invoice, the resulting line items could be: | Line item | Quantity | Price | Amount due | | - | - | - | - | | GPU Usage — Reserved | 89,280 GPU-hours | \$0.00 / GPU-hour | \$0.00 | | GPU Usage — On-Demand | 59,520 GPU-hours | \$2.00 / GPU-hour | \$119,040 | | Reservation Fee | 1 month | \$100,000 / month | \$100,000 | | **Invoice Total** | | | **\$219,040** | The reserved-usage line item shows the customer how much capacity was covered by their reservation. The reservation fee and on-demand line item determine the amount due. Use invoice breakdowns to give customers hourly or daily visibility into covered and on-demand usage. This helps customers reconcile capacity consumption, reservation coverage, and overages. ## Best practices * **Keep usage events immutable.** Store actual consumption in usage events and calculate the reservation classification from the contract rather than rewriting historical events. * **Use the same evaluation interval as the usage events.** If events are sent every 60 seconds, apply the reservation to each 60-second interval before rolling up to the billing-period total. * **Align schedule properties with the reservation scope.** If capacity is reserved by SKU, use `sku` as the schedule property. Include `region` or other dimensions only when the commercial reservation is scoped to those dimensions. ## Conclusion Provisioned-throughput billing combines predictable committed revenue with flexible usage-based overages. Metronome keeps raw capacity usage immutable, stores changing commitments on the contract through Named Schedules, and uses SQL billable metrics to calculate the covered and on-demand quantities for each billing interval. This model gives customers transparent visibility into how their reserved capacity is used while ensuring that contract changes are accurately reflected in billing. # Billing for LLM tokens 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 > [!NOTE] > > **Public preview** > > Billing for LLM tokens is in public preview. We will continue to build on the product and there may be quick changes! ## Set up with an AI coding agent Use the [Metronome billing for LLM tokens 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 billing for LLM tokens 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 billing for LLM tokens, 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:** Billing for LLM tokens uses a USD rate card because provider prices are denominated in USD. To let customers pay in their local currency, see [Let customers pay in their local currency](#let-customers-pay-in-their-local-currency). ### 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**. ## Let customers pay in their local currency Managed AI rate cards use USD, but customers can pay in their local currency, such as EUR, with Stripe [Adaptive Pricing](https://docs.stripe.com/payments/currencies/localize-prices/adaptive-pricing?payment-ui=invoices). You keep your managed USD rate card, so Metronome continues to sync newly released models and provider price changes. Invoices remain in USD, and Stripe shows customers a converted amount when they pay. To use Adaptive Pricing with Metronome invoices: * Set the customer's [`stripe_collection_method`](/integrations/invoice-integrations/stripe) to `send_invoice`. Adaptive Pricing for invoices applies when customers pay on the Stripe hosted invoice page. * Make sure USD is one of your Stripe settlement currencies, because Stripe requires invoices to be issued in a settlement currency. To add USD, see [multi-currency settlement](https://docs.stripe.com/payouts/multi-currency-settlement). To enable Adaptive Pricing and review supported countries, restrictions, and fees, see the [Stripe Adaptive Pricing docs](https://docs.stripe.com/payments/currencies/localize-prices/adaptive-pricing?payment-ui=invoices). ## 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. > [!NOTE] > > You can choose to collect a payment method when the user signs up, even for a free tier. This can help prevent abuse when a free tier includes a free credit allocation. 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_BEARER_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_BEARER_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`: Uncached input tokens * `cached_input_tokens`: Cache-read input tokens * `output_tokens`: Tokens in the response * `cached_write_tokens`: Cache-write tokens. Supported for Anthropic models and OpenAI GPT-5.6+ models only ### Map provider token counts Providers report token usage in different shapes. Some include cached tokens in their total input count, while others report them separately. Before you send an event, convert the provider's counts so that each token appears in exactly one property. For example, a cache-read token belongs in `cached_input_tokens` only, not in `input_tokens` as well. When a provider leaves out an optional count, such as cache writes for a request that didn't write to the cache, use `0` in your calculation. In the event, you can send that property as `0` or leave it out. Either way, Metronome bills no tokens of that type. For streaming responses, send the event after the stream finishes and the provider reports final usage. Don't estimate token counts from partial output. #### OpenAI Responses The [Responses API `usage` object](https://developers.openai.com/api/reference/resources/responses/methods/create) includes cache reads and cache writes in `input_tokens`. Subtract them to get ordinary input: ```text theme={null} cache_reads = usage.input_tokens_details?.cached_tokens ?? 0 cache_writes = usage.input_tokens_details?.cache_write_tokens ?? 0 input_tokens = usage.input_tokens - cache_reads - cache_writes cached_input_tokens = cache_reads cached_write_tokens = cache_writes output_tokens = usage.output_tokens ``` For example, given this API response: ```json theme={null} { "usage": { "input_tokens": 16000, "input_tokens_details": { "cached_tokens": 12000, "cache_write_tokens": 3000 }, "output_tokens": 400 } } ``` Send these values in the usage event's `properties`: ```json theme={null} { "input_tokens": 1000, "cached_input_tokens": 12000, "cached_write_tokens": 3000, "output_tokens": 400 } ``` #### OpenAI Chat Completions The [Chat Completions API `usage` object](https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create) includes cache reads and cache writes in `prompt_tokens`. Subtract them to get ordinary input: ```text theme={null} cache_reads = usage.prompt_tokens_details?.cached_tokens ?? 0 cache_writes = usage.prompt_tokens_details?.cache_write_tokens ?? 0 input_tokens = usage.prompt_tokens - cache_reads - cache_writes cached_input_tokens = cache_reads cached_write_tokens = cache_writes output_tokens = usage.completion_tokens ``` For streaming requests, set `stream_options.include_usage` to `true` so that the final chunk includes `usage`. For example, given this API response: ```json theme={null} { "usage": { "prompt_tokens": 16000, "prompt_tokens_details": { "cached_tokens": 12000, "cache_write_tokens": 3000 }, "completion_tokens": 400 } } ``` Send these values in the usage event's `properties`: ```json theme={null} { "input_tokens": 1000, "cached_input_tokens": 12000, "cached_write_tokens": 3000, "output_tokens": 400 } ``` #### Anthropic Messages The [Messages API `usage` object](https://platform.claude.com/docs/en/api/messages) reports ordinary input, cache reads, and cache writes as separate counts. Map them directly: ```text theme={null} input_tokens = usage.input_tokens cached_input_tokens = usage.cache_read_input_tokens ?? 0 cached_write_tokens = usage.cache_creation_input_tokens ?? 0 output_tokens = usage.output_tokens ``` For example, given this API response: ```json theme={null} { "usage": { "input_tokens": 1000, "cache_read_input_tokens": 12000, "cache_creation_input_tokens": 3000, "output_tokens": 400 } } ``` Send these values in the usage event's `properties`: ```json theme={null} { "input_tokens": 1000, "cached_input_tokens": 12000, "cached_write_tokens": 3000, "output_tokens": 400 } ``` #### Google Gemini `generateContent` For text requests without tool use, the [`UsageMetadata` object](https://ai.google.dev/api/generate-content#UsageMetadata) includes cache reads in `promptTokenCount`. Subtract them to get ordinary input. [Thinking tokens count toward output pricing](https://ai.google.dev/gemini-api/docs/pricing), so add them to output. Gemini doesn't report cache writes, so leave out `cached_write_tokens`: ```text theme={null} cache_reads = usageMetadata.cachedContentTokenCount ?? 0 input_tokens = usageMetadata.promptTokenCount - cache_reads cached_input_tokens = cache_reads output_tokens = (usageMetadata.candidatesTokenCount ?? 0) + (usageMetadata.thoughtsTokenCount ?? 0) ``` For example, given this API response: ```json theme={null} { "usageMetadata": { "promptTokenCount": 13000, "cachedContentTokenCount": 12000, "candidatesTokenCount": 300, "thoughtsTokenCount": 100 } } ``` Send these values in the usage event's `properties`: ```json theme={null} { "input_tokens": 1000, "cached_input_tokens": 12000, "output_tokens": 400 } ``` 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. ## Test your end to end flow To test your integration: 1. Create a webhook destination by navigating to Developer > Notifications > Webhooks. 2. Create a test customer. 3. Provision the test customer using the rate card that you just created. 4. Send in usage events with the test customer's `customer_id`. 5. Call the `getInvoice` endpoint to view the customer's spend, and validate that each line item looks correct based on the markup you configured. ## Add models to your rate card Use the [Metronome billing for LLM tokens agent skill](/.well-known/agent-skills/metronome-token-billing/skill.md) to add one or more models to an existing rate card. Tell the agent which models to add and which rate card to use and the agent will confirm the correct markup and rates and add them to your rate card. ## Update your markup percentage Use the [Metronome billing for LLM tokens agent skill](/.well-known/agent-skills/metronome-token-billing/skill.md) to update the markup percentage for an individual model or every model on a rate card. ## 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] > > **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. > [!NOTE] > > **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" } } ] } ] }' ``` > [!NOTE] > > **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. > [!NOTE] > > **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 | | AED | HKD | RON | PHP | | ILS | THB | PKR | | > [!NOTE] > > **Private Preview** > > Metronome supports JPY in private preview. Reach out through the support portal to enable this currency. ### 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`. > [!WARNING] > > **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] > > **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](https://mintcdn.com/metronome-b35a6a36/RmXuQ2v0AyTvK_BJ/images/docs/pricing-packaging/make-pricing-changes/set-currencies/rate-card-cpus-3edd3d4d6741cc8ba3a7bcdaf820c8cc.png?fit=max\&auto=format\&n=RmXuQ2v0AyTvK_BJ\&q=85\&s=0dc931705d0dda1fe27cddf3d8eb8f15) 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](https://mintcdn.com/metronome-b35a6a36/RmXuQ2v0AyTvK_BJ/images/docs/pricing-packaging/make-pricing-changes/set-currencies/commit-cpus-bdc5717f85aae1f063279ae38bb37e9f.png?fit=max\&auto=format\&n=RmXuQ2v0AyTvK_BJ\&q=85\&s=39a650056100ff806df4998c0e1d86c8) ## 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](https://mintcdn.com/metronome-b35a6a36/RmXuQ2v0AyTvK_BJ/images/docs/pricing-packaging/make-pricing-changes/set-currencies/invoice-cpus-854f8264660559e94a2b881ac1449af2.png?fit=max\&auto=format\&n=RmXuQ2v0AyTvK_BJ\&q=85\&s=e4c73bc52ad77b5e408e19d9d602be0f) # 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. > [!NOTE] > > **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] > > **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. ## Get notified about subscription lifecycle events Metronome can notify your [webhooks](/guides/platform-configuration/webhooks/webhook-types) when a subscription is created, starts, or ends. Use these notifications to keep your product, CRM, and customer communications in sync with Metronome without polling the API. There are two ways to use them: * [System notifications](/guides/customers-billing/set-up-notifications/system-notifications) fire when the subscription event happens. * [Offset notifications](/guides/customers-billing/set-up-notifications/offset-notifications) fire at a set time before or after the subscription event. ### React to subscription events with system notifications | **Notification** | **When it fires** | **Example workflows** | | - | - | - | | `subscription.create` | A new subscription is created on a contract | Record the new plan or add-on in your CRM or data warehouse. Alert the account team when a customer adds a subscription to an existing contract. | | `subscription.start` | A subscription reaches its start date | Grant access to the plan's features. Send a welcome email when a future-dated subscription takes effect, such as the paid subscription that follows a free trial. | | `subscription.end` | A subscription reaches its end date | Revoke access to the plan's features. Start an offboarding or win-back flow after a customer cancels. | Each notification includes the subscription, contract, and customer IDs along with their custom fields, so your webhook handler can match the event to the right account in your system. ### Plan ahead with offset notifications Offsets let you act before a subscription event happens, or follow up after it. See [enabling and managing offset notifications](/guides/customers-billing/set-up-notifications/offset-notifications#enabling-and-managing-offset-notifications) to set one up. | **Scenario** | **When it fires** | **Workflow details** | | - | - | - | | Trial ending reminder | 3 days before `subscription.end` | If you model a free trial as a separate \$0 subscription, email the customer before the trial ends and their paid subscription starts. | | Renewal outreach | 30 days before `subscription.end` | Alert the account owner so they can start a renewal conversation before a fixed-term subscription expires. | | Onboarding nudge | 2 days after `subscription.start` | Send setup tips or remind the customer to invite teammates to their seats. | | Post-purchase check-in | 14 days after `subscription.create` | Send a satisfaction survey or schedule a call with customer success. | System and offset notifications apply to all customers. If a workflow should only run for some subscriptions, such as trials, tag those subscriptions with a [custom field](/api-reference/custom-fields), such as `trial`, and check `subscription_custom_fields` in your webhook handler before acting. # Payment gate a subscription Source: https://docs.metronome.com/guides/pricing-packaging/subscription/payment-gate-subscriptions This page describes how to require payment before granting access to a subscription or its recurring credits. Payment gating lets Metronome track the paid subscription quantity, release attached credits according to payment status, and notify your application when the entitlement state changes. > [!NOTE] > > **Private preview** > > This page documents a private preview. Contact your Metronome representative to confirm access before using these provisional fields and endpoints. The API can change during the preview. Use payment gating to reduce fraud risk and ensure that you collect payment before granting customers access to your products or credits. This is especially important for AI companies, where unpaid usage can incur substantial compute costs. For example, if you sell a \$10 monthly subscription that includes 100 AI credits, payment gating lets you easily withhold credit access until the initial payment succeeds and after each corresponding renewal invoice is paid. ## How payment-gated subscriptions work Payment-gated subscriptions introduce a `status` field that reflects subscription payment outcomes and helps your application manage entitlements. Metronome handles invoicing, payment-status tracking, and linked credit releases. Metronome also releases webhooks to enable you to grant or revoke access to your product. 1. **Metronome initiates payment.** On the scheduled invoice date, Metronome creates and finalizes the subscription invoice, sends it to Stripe Invoicing, and triggers an immediate payment attempt. 2. **Metronome updates the subscription state.** If payment succeeds, Metronome sets the subscription status to `ACTIVE`, updates the paid quantity of the subscription, sends a `subscription.payment_gate_status` webhook, and releases linked recurring credits according to their access policy. If payment fails, Metronome withholds credit release and sends a corresponding webhook. 3. **Your application updates entitlements.** Use Metronome webhooks and status reads to grant access for the paid quantity or block or suspend access after payment failure. Metronome updates the subscription's billing state; it doesn't directly enable or disable users in your application. Listen to Stripe webhooks for detailed payment failure reasons. ## Before you begin * [Set up your subscription pricing](/guides/pricing-packaging/subscription/define-subscription-pricing). * Configure your Stripe integration. Payment-gated subscriptions currently support only Stripe Invoicing. Ensure that each Stripe customer has a default payment method and a valid stored customer address. Without these, payment attempts fail. * Set up your webhook listeners. Listen for Metronome subscription status webhooks to manage entitlements. Also listen to Stripe webhooks for detailed PaymentIntent actions, such as 3DS authentication, and payment failure details. ## Configure payment gating For a hybrid pricing model that combines a subscription with recurring credits, configure two parts: * **Subscription payment gate:** Set `payment_gate_config` on the subscription. Metronome automatically tracks payment status on the subscription invoice and updates the subscription status so your application can manage access and quantity changes. You can configure a subscription payment gate with or without recurring credits. * **Recurring credit access policy:** Set `subscription_config.access_policy` on the linked recurring credit. Metronome manages credit releases based on subscription payment status and the policy you choose: require payment for each billing period, only the initial billing period, or neither. The linked subscription must have a payment gate configured. ### Create a payment-gated subscription Create a payment-gated subscription in the Metronome app or through the API, either when creating a new contract or when adding a subscription to an existing contract. Ensure that both the customer and the contract in Metronome have a valid Stripe billing provider configuration or subscription creation will fail. Consider an AI company that offers a \$10 monthly subscription with 100 AI credits included. The company bills the subscription at the start of each month and grants that month's credits only after payment succeeds. The following API call creates a contract for a new customer with a payment-gated subscription and linked recurring credits. ```bash cURL theme={null} curl --request POST \ --url https://api.metronome.com/v1/contracts/create \ --header "Authorization: Bearer $METRONOME_API_KEY" \ --header "Content-Type: application/json" \ --data '{ "customer_id": "4c09936b-455d-4c72-a120-d71b600a7546", "rate_card_id": "740a2ca1-64f6-417d-807a-05f154b3b1fe", "starting_at": "2026-10-01T00:00:00Z", "billing_provider_configuration": { "billing_provider_configuration_id": "e045c62b-65e7-4e84-a924-3f06f8b621d0" }, "subscriptions": [ { "temporary_id": "ai_starter_monthly", "name": "AI Starter", "collection_schedule": "advance", "initial_quantity": 1, "subscription_rate": { "billing_frequency": "monthly", "product_id": "ed518bcb-acc1-4cd8-85dd-880c2eb38994" }, "proration": { "invoice_behavior": "bill_immediately", "is_prorated": true }, "payment_gate_config": { "payment_gate_type": "STRIPE", "tax_type": "STRIPE" } } ], "recurring_credits": [ { "access_amount": { "credit_type_id": "d3cb2827-dcb5-44af-9354-947a7197b9a6", "unit_price": 100 }, "subscription_config": { "subscription_id": "ai_starter_monthly", "access_policy": "BILLING_PERIOD_PAID" } } ] }' ``` Metronome creates and finalizes the subscription invoice and sends it to Stripe for a payment attempt. Metronome updates the subscription status when the payment succeeds or fails. While payment is pending or in flight, the subscription status remains unchanged. Use the [`getSubscriptionStatus` API](#read-subscription-state-through-the-api) to inspect pending updates in `open_invoices`. Don't grant access based on invoice creation or an in-progress payment. See [Manage entitlements](#manage-entitlements) for more detail. ## Choose when to release recurring credits As shown in the API call above, attach a recurring credit or commit through `subscription_config.subscription_id`. When you create the subscription and credit in the same request, use the subscription's `temporary_id`. Set `subscription_config.access_policy` to control whether payment gates the credit release. This field is required when the recurring credit or commit is linked to a payment-gated subscription. | Access policy | Definition | Use when | | - | - | - | | `BILLING_PERIOD_PAID` | Metronome releases each period's credits after payment for that period succeeds. The initial payment and every renewal gate their corresponding credits. | Use if you are a company with high fraud risk and need to ensure payment each billing period regardless of customer history. | | `INITIAL_BILLING_PERIOD_PAID_ONLY` | Metronome releases credits after the initial subscription payment succeeds. Later releases don't wait for renewal payment. | Use when the highest risk vector is on initial sign-up or when you want to to avoid disruptive product experiences upon payment failure for customers with an existing payment history. | > [!NOTE] > > **First-of-month processing** > > A recurring credit gated on billing-period payment can take several hours to release when many subscriptions renew on the first day of the month. Gate only on initial billing period if you want to customers to have access to credits immediately when the new billing period begins. ## Change subscription quantity Suppose the AI company above adds a team plan where each seat costs \$10 per month and includes 100 AI credits. A customer with one paid seat requests a second seat halfway through the month. Use the [edit contract API](/api-reference/contracts/edit-a-contract) to increase the subscription quantity by one, as shown below. See [Manage seats](/guides/pricing-packaging/subscription/manage-seats) for more information about quantity changes and linked credit behavior. Metronome creates an invoice for the additional seat and triggers payment in Stripe. With the example's proration settings, the charge is prorated for the remaining billing period. While payment is pending, `paid_quantity` remains `1`; don't grant access to the additional seat yet. ```bash cURL theme={null} curl --request POST \ --url https://api.metronome.com/v2/contracts/edit \ --header "Authorization: Bearer $METRONOME_API_KEY" \ --header "Content-Type: application/json" \ --data '{ "customer_id": "4c09936b-455d-4c72-a120-d71b600a7546", "contract_id": "7f865c1b-1c08-40e8-9c09-b3238fd3b50d", "update_subscriptions": [ { "subscription_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "quantity_updates": [ { "quantity_delta": 1, "starting_at": "2026-10-15T12:00:00Z" } ] } ] }' ``` If payment succeeds, Metronome automatically updates the subscription quantity and releases additional linked credits. Metronome sends a webhook that your application can use to grant access to the second seat. If payment fails, Metronome automatically voids the quantity-change invoices in both Stripe and Metronome and doesn't apply the seat increase. The original paid seat remains available. After the customer resolves the payment issue, retry by requesting the additional seat again; Metronome creates a new invoice and payment attempt. > [!NOTE] > > **One pending quantity change at a time** > > Only one quantity change can be pending for a subscription at a time. While it is pending, no further changes are allowed except removing the pending change or ending the subscription. If a pending quantity change is not paid within one hour, Metronome automatically rolls back the quantity change and voids the corresponding invoices. ## Manage entitlements Use subscription status and paid quantity to determine product access, and use webhooks to keep your application's entitlements up to date. ### Subscription statuses | Status | Definition | Entitlement behavior | | - | - | - | | `NOT_STARTED` | The subscription hasn't reached its start date or its initial payment hasn't completed. | Don't grant access. | | `INCOMPLETE` | The initial subscription payment failed. No new invoices will be generated and subscription quantity cannot be changed. | Don't grant access, potentially kick-off additional fraud prevention flows. | | `ACTIVE` | The latest subscription-cycle payment succeeded. Pending quantity increases don't change the paid quantity until payment succeeds. | Grant access for `paid_quantity`. | | `UNPAID` | A recurring subscription payment failed. If subscription is not ended, renewal invoices will continue to be generated, but subscription quantity cannot be changed. | Revoke or suspend access according to your product policy. If the latest renewal invoice is paid, access can be regranted for the current billing period. | | `ENDED` | The subscription has ended. This status is terminal. | Revoke access. Create a new subscription or contract if the customer restarts. | ### Handle subscription webhooks Use Metronome webhooks to understand when payment is updated and manage product access. Metronome sends `subscription.payment_gate_status` whenever the paid quantity, subscription status, or external invoice is updated, except for the transition to `ENDED`. This includes successful renewals and quantity changes even when the subscription remains `ACTIVE`. Enable lifecycle events separately to handle subscription endings. Treat Metronome as the source of truth for entitlement state and Stripe as the source of truth for payment actions. 1. Listen for `subscription.payment_gate_status` and enabled lifecycle events. 2. Read the updated `status` and `paid_quantity` to determine the customer's entitlement. 3. Grant or update access for the paid quantity when the subscription is `ACTIVE`. 4. Block or suspend access after an unsuccessful initial or renewal payment, according to your product policy. Remove access when the subscription ends. 5. Make webhook handlers idempotent and use webhook delivery retries to recover from failed processing. The following example shows a successful payment for an initial sign-up of one subscription seat. ```json theme={null} { "id": "dba7c77a-4ccb-4280-a45b-8d43fc6ae3d0", "type": "subscription.payment_gate_status", "properties": { "customer_id": "4c09936b-455d-4c72-a120-d71b600a7546", "contract_id": "7f865c1b-1c08-40e8-9c09-b3238fd3b50d", "subscription_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2", "status": "ACTIVE", "paid_quantity": 1, "invoice_id": "0f159078-7915-4b3c-97ea-9a6bb7a8d638", "changes": [ "status", "paid_quantity", "invoice_id", "external_invoice.invoice_id", "external_invoice.external_status", "external_invoice.payment_intent_id" ], "external_invoice": { "invoice_id": "in_123", "payment_intent_id": "pi_123", "external_status": "PAID" } } } ``` Use `changes` to understand why an event arrived, but use the updated `status` and `paid_quantity` to set entitlements. Note that a successful renewal can update the invoice fields without changing the subscription's status or paid quantity. > [!WARNING] > > **Enable lifecycle events** > > [Lifecycle events](https://docs.metronome.com/guides/customers-billing/set-up-notifications/system-notifications) aren't enabled automatically. Enable them for your webhook destination. An `ENDED` subscription doesn't produce a `subscription.payment_gate_status` event. Use lifecycle events to remove access at the subscription end date. ### Read subscription state through the API Use the `getSubscriptionStatus` API to programmatically view subscription state, reconcile entitlements, or check whether a payment is still pending. Pending or in-flight payments don't update subscription status; inspect `open_invoices` for payable invoices and pending quantity changes. Don't grant access based on an entry in `open_invoices`. The response includes the following fields: * `status` represents the subscription's current payment-backed lifecycle state. * `paid_quantity` is the quantity your application can entitle. During a pending quantity increase, it remains at the last successfully paid quantity. * `latest_cycle_invoice` describes the latest subscription-cycle invoice with a conclusive payment outcome, whether successful or unsuccessful. It doesn't represent a mid-period quantity-change invoice. * `open_invoices` lists payable subscription-cycle and quantity-change invoices that haven't reached a terminal state. Use this field for diagnostics, not to grant access. ```bash cURL theme={null} curl --request POST \ --url https://api.metronome.com/v1/subscriptions/getStatus \ --header "Authorization: Bearer $METRONOME_API_KEY" \ --header "Content-Type: application/json" \ --data '{ "customer_id": "4c09936b-455d-4c72-a120-d71b600a7546", "contract_id": "7f865c1b-1c08-40e8-9c09-b3238fd3b50d", "subscription_id": "2714e483-4ff1-48e4-9e25-ac732e8f24f2" }' ``` For example, a customer has paid for one seat and requests a second seat. While payment for the additional seat is pending, the response shows the original paid quantity and an open quantity-change invoice: ```json theme={null} { "status": "ACTIVE", "paid_quantity": 1, "latest_cycle_invoice": { "id": "0f159078-7915-4b3c-97ea-9a6bb7a8d638", "starting_at": "2026-10-01T00:00:00Z", "ending_before": "2026-11-01T00:00:00Z", "quantity": 1, "external_invoice": { "invoice_id": "in_123", "external_status": "PAID" } }, "open_invoices": [ { "id": "7f7c8958-83c6-4efa-91fd-593a50c9e196", "starting_at": "2026-10-15T12:00:00Z", "ending_before": "2026-11-01T00:00:00Z", "quantity": 1, "reason": "subscription_quantity_update", "external_invoice": { "invoice_id": "in_seat_upgrade_123", "external_status": "OPEN" } } ] } ``` In the preceding response, a subscription quantity-update invoice is still in flight. Metronome has sent it to Stripe, but payment hasn't succeeded, so the Stripe invoice status remains `OPEN`. ## Handle payment failures Listen to Stripe invoice and PaymentIntent webhooks to handle detailed payment failures and customer actions such as 3DS authentication. For example, `invoice.payment_action_required` indicates that the customer must complete an authentication action. Use Metronome subscription webhooks to manage product access and Stripe webhooks to guide the customer through resolving the payment issue. ### Recover initial and renewal payments Initial and renewal invoices have a 13-day payment window to accommodate payment methods such as ACH and give you time to handle payment recovery. This window isn't an entitlement grace period: a failed payment still updates subscription status so your application can block or suspend access. Unlike failed quantity-change invoices, initial and renewal invoices remain payable during this window. For example, if a renewal payment fails: 1. Metronome sends a `subscription.payment_gate_status` webhook with status `UNPAID`. Your application suspends access according to your product policy. 2. Stripe sends a payment-failure notification. Your application prompts the customer to update their payment method or complete a required authentication action. 3. The customer resolves the issue and the invoice is paid within the payment window. 4. Metronome updates the subscription to `ACTIVE`, sends a webhook, and releases credits as applicable. Your application restores access for `paid_quantity`. If an initial payment fails, the same recovery flow applies with status `INCOMPLETE` instead of `UNPAID`. ### Invoice expiration If payment doesn't succeed within 13 days, Metronome automatically voids the Stripe invoice, which also voids the corresponding Metronome invoice. All open invoices expire at the end of their billing period, even if the 13-day window hasn't elapsed. The effective deadline is the earlier of the 13-day payment deadline and the billing-period end. Your Stripe payment recovery settings, including Smart Retries, continue to apply automatically while the invoice remains open. Use Stripe webhooks to handle payment recovery actions. Failed quantity-change invoices don't use this recovery window: retry those by requesting the seat increase again. ## Private preview limits The following configuration limits apply during the private preview: * Quantity-based subscriptions only. Seat-based subscriptions that track individual seat IDs aren't supported yet. * Payment gated subscriptions must be billed in-advance (`collection_schedule: "advance"`) and quantity updates billed immediately (`proration.invoice_behavior: "bill_immediately"`). * Stripe Tax and Stripe Invoicing are the only supported downstream tax and invoicing systems. * Invoice placement must be set on the scheduled invoice and cannot be combined with usage invoices. # 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] > > **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" } } ] } ``` > [!NOTE] > > **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). > [!NOTE] > > **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://app.metronome.com/support) 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] > > **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] > > **TIP** > > By default, Metronome supports up to 1000 seats with individual seat credits. Contact us via the [Metronome support portal](https://app.metronome.com/support) 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: **1. Define the group key on your billable metric** 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. > [!NOTE] > > 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. **2. Add the presentation group key to your product** 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. **3. Include seat\_id in your usage events** 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](https://mintcdn.com/metronome-b35a6a36/C_lGxKgdkdHt6xoX/images/docs/pricing-packaging/manage-contracts/create-subscription/subscription-data-model-d9853d14d7b23497d8f1c34b59f26f84.png?fit=max\&auto=format\&n=C_lGxKgdkdHt6xoX\&q=85\&s=65de2014fd6c80c8957eb9d1cace44fa) ### 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 > [card] [Define subscription pricing](/guides/pricing-packaging/subscription/define-subscription-pricing) > > Create subscription products and add them to your rate card to define standard list prices. > [card] [Provision your customer](/guides/pricing-packaging/subscription/provision-your-customer) > > Create contracts for your customers based on the subscription plan they choose. Supports standard subscription recurring fees and hybrid credit models. > [card] [Manage seats](/guides/pricing-packaging/subscription/manage-seats) > > 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. > [card] [Subscription lifecycle](/guides/pricing-packaging/subscription/manage-subscription-lifecycle) > > Model 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. > [!TIP] > > 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 > [accordion] Fetch total active 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 > [accordion] Fetch event count per month > > 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 > [accordion] Fetch monthly invoice totals > > 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) > [accordion] Fetch monthly totals by line item type > > 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 > [accordion] Fetch daily draft invoice totals > > 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) > [accordion] Fetch draft invoice total by contract from most recent snapshot > > 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 > [accordion] Fetch daily draft aggregate line item quantity and total > > 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) > [accordion] Fetch daily draft invoice line item totals by customer > > 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 > [accordion] Fetch archived 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) > [accordion] Fetch the most recent overrides on a contract > > 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) > > > [!TIP] > > > > Replace `` with your actual contract ID. > [accordion] Fetch active rate card entry count per rate card > > 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 > [accordion] Fetch alerts with webhooks enabled > > 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) > [accordion] Fetch count of alerts by day over the last week > > 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). > [!NOTE] > > **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. > [accordion] billable\_metric > > ### `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 | > [accordion] credit\_type > > ### `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. > [accordion] events > > ### `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. > [accordion] customer > > ### `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 | > [accordion] customer\_billing\_provider\_configuration > > ### `customer_billing_provider_configuration` > > One row per billing provider configuration. A customer can have more than one configuration. > > | Column | Type | Description | > | - | - | - | > | `id` | `string` | The ID of the billing provider configuration | > | `environment_type` | `string` | The Metronome environment, `SANDBOX` or `PRODUCTION` | > | `customer_id` | `string` | The Metronome ID of the customer | > | `billing_provider` | `string` | The billing provider of the configuration (e.g. Stripe) | > | `configuration` | `string` | JSON-encoded provider-specific settings, such as the customer's ID in the billing provider | > | `unbillable_invoices_configuration` | `string` | JSON-encoded array of the configuration's unbillable invoice rules, each with an `invoice_type`, `fiat_credit_type_id`, and `max_amount` | > | `external_account_information` | `string` | JSON-encoded identifiers of the billing provider account or delivery destination, such as the Stripe account ID | > | `status` | `string` | The configuration status: `PENDING`, `ACTIVE`, `ERROR`, or `ARCHIVED` | > | `created_at` | `timestamp` | The timestamp (UTC) of when the configuration was created | > | `updated_at` | `timestamp` | The timestamp (UTC) of when the configuration was last updated | > | `archived_at` | `timestamp` | The timestamp (UTC) of when the configuration 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. > [accordion] invoice > > ### `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` | > | `billable_status` | `string` | Billable status of the invoice, `BILLABLE` or `UNBILLABLE` | > | `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_configuration_id` | `string` | The ID of the billing provider configuration Metronome used when it processed the invoice for its billing provider. Joins to `customer_billing_provider_configuration.id`. A later configuration change does not update this ID unless the invoice's billable status also changes | > | `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 | > [accordion] line\_item > > ### `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. > [accordion] draft\_invoice > > ### `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 | > | `billing_provider_configuration_id` | `string` | The ID of the billing provider configuration for the invoice. Joins to `customer_billing_provider_configuration.id` | > | `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 | > [accordion] draft\_line\_item > > ### `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. > [!NOTE] > > **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://app.metronome.com/support). > [accordion] breakdowns\_invoices > > ### `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 | > [accordion] breakdowns\_line\_items > > ### `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 | > [accordion] breakdowns\_draft\_invoices > > ### `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 | > | `billing_provider_configuration_id` | `string` | The ID of the billing provider configuration for the parent invoice. Joins to `customer_billing_provider_configuration.id` | > | `amendment_id` | `string` | The amendment ID associated with the invoice | > | `custom_fields` | `json` | Custom fields that apply to the invoice | > | `billable_status` | `string` | The parent 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 | > [accordion] breakdowns\_draft\_line\_items > > ### `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. > [accordion] contracts\_contracts > > ### `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 | > | `billing_provider_configuration_id` | `string` | The ID of the contract's billing provider configuration at the time of the snapshot. Joins to `customer_billing_provider_configuration.id`. See `contracts_billing_provider_configuration_schedule` for the full schedule | > | `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". | > | `usage_statement_schedule_billing_anchor_date` | `timestamp` | The timestamp (UTC) that the contract's usage statement periods are aligned to. Period boundaries fall on this date and recur at `usage_statement_schedule_frequency`. This date may be before the contract starts, in which case the first usage statement covers a partial period from the contract start to the next boundary. | > | `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 | > [accordion] contracts\_billing\_provider\_configuration\_schedule > > ### `contracts_billing_provider_configuration_schedule` > > One row per interval in a contract's billing provider configuration schedule. > > | Column | Type | Description | > | - | - | - | > | `id` | `string` | The ID of the schedule interval | > | `environment_type` | `string` | The Metronome environment, `SANDBOX` or `PRODUCTION` | > | `customer_id` | `string` | The customer ID of the contract | > | `contract_id` | `string` | The ID of the contract | > | `billing_provider_configuration_id` | `string` | The ID of the billing provider configuration for this interval, or null if the interval has none. Joins to `customer_billing_provider_configuration.id` | > | `effective_at` | `timestamp` | The timestamp (UTC) when the interval starts (inclusive) | > | `effective_until` | `timestamp` | The timestamp (UTC) when the interval ends (exclusive), or null if the interval has no end | > | `updated_at` | `timestamp` | The timestamp (UTC) of when the schedule was last updated | > [accordion] contracts\_commits > > ### `contracts_commits` > > > [!NOTE] > > > > 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 | > | `moved_to_history_at` | `timestamp` | The timestamp (UTC) of when the commit was moved to history, or null if it has not been moved to history. | > > #### `contracts_commits.AccessSchedule` > > ```typescript theme={null} > interface AccessSchedule { > access_type: "quantity" | "spend"; > 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; > }; > } > ``` > [accordion] contracts\_balances > > ### `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 | > | `moved_to_history_at` | `timestamp` | The timestamp (UTC) of when the credit or commit was moved to history, or null if it has not been moved to history. | > > #### `contracts_balances.AccessSchedule` > > ```typescript theme={null} > interface AccessSchedule { > access_type: "quantity" | "spend"; > 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; > }; > } > ``` > [accordion] contracts\_recurring\_commits\_and\_credits > > > [!NOTE] > > > > 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 { > access_type: "quantity" | "spend"; > 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; > access_policy?: "BILLING_PERIOD_PAID" | "INITIAL_BILLING_PERIOD_PAID_ONLY" | null; > }; > ``` > > `access_policy` is null or absent when no access policy is configured. > With `BILLING_PERIOD_PAID`, the subscription period corresponding to the credit period must be paid in order for access to be granted. > With `INITIAL_BILLING_PERIOD_PAID_ONLY`, all credits will be released after the subscription's initial period is paid. > [accordion] contracts\_usage\_filter\_schedule > > > [!TIP] > > > > 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 | > [accordion] contracts\_usage\_filters > > ### `contracts_usage_filters` > > > [!TIP] > > > > 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 | > [accordion] contracts\_prepaid\_balance\_threshold\_configurations > > ### `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` | > [accordion] contracts\_spend\_threshold\_configurations > > ### `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 | > [accordion] contracts\_subscriptions > > ### `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 | > | `status` | `string` | The subscription status at export time: `NOT_STARTED`, `INCOMPLETE`, `ACTIVE`, `UNPAID`, or `ENDED`. Null for subscriptions without payment gating. | > | `payment_gate_config` | `json` | [`PaymentGateConfig`](/guides/reporting-insights/data-export/database-reference/#contracts_subscriptions-paymentgateconfig) - Null for subscriptions without payment gating. | > > #### `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_subscriptions.PaymentGateConfig` > > The payment gate configuration specifies the payment provider and tax provider for the subscription. > > ```typescript theme={null} > interface PaymentGateConfig { > type: "STRIPE"; > tax: "NONE" | "STRIPE" | null; > } > ``` > > For example: > > ```json theme={null} > { > "type": "STRIPE", > "tax": "NONE" > } > ``` > [accordion] contracts\_subscription\_seat\_balances > > ### `contracts_subscription_seat_balances` > > One row per subscription seat and seat-specific prepaid commit or credit. > > | Column | Type | Description | > | - | - | - | > | `id` | `string` | Unique row ID formed from the contract ID, seat ID, and commit or credit ID | > | `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 contract | > | `contract_id` | `string` | The contract ID that scopes the seat balance | > | `seat_id` | `string` | The seat ID specified when the seat was added to the subscription | > | `commit_or_credit_id` | `string` | The ID of the underlying commit or credit | > | `type` | `string` | `commit` or `credit` | > | `balance` | `float` | The current balance remaining for this seat's commit or credit | > | `starting_at` | `timestamp` | The timestamp (UTC) when the commit or credit becomes active, inclusive | > | `ending_before` | `timestamp` | The timestamp (UTC) when the commit or credit expires, exclusive; null if no end is set | > | `access_type` | `string` | How the balance is drawn down: `spend` or `quantity` | > | `credit_type_id` | `string` | The credit type ID for `spend` access; `00000000-0000-0000-0000-000000000000` for `quantity` access | > | `ledger` | `json` | [`SeatLedgerEntry[]`](/guides/reporting-insights/data-export/database-reference#contracts-subscription-seat-balances-seatledgerentry) | > | `updated_at` | `timestamp` | The timestamp (UTC) at which this row was exported | > > #### `contracts_subscription_seat_balances.SeatLedgerEntry` > > ```typescript theme={null} > type SeatLedgerEntry = > | { > type: "prepaid_segment_start"; > /** ISO-8601 formatted timestamp */ > timestamp: string; > /** Float */ > amount: number; > segment_id: string; > } > | { > type: "prepaid_seat_based_adjustment"; > /** ISO-8601 formatted timestamp */ > timestamp: string; > /** Float */ > amount: number; > segment_id: string; > } > | { > type: "prepaid_automated_invoice_deduction"; > /** ISO-8601 formatted timestamp */ > timestamp: string; > /** Float */ > amount: number; > segment_id: string; > invoice_id: string; > contract_id: string; > } > | { > type: "prepaid_manual"; > /** ISO-8601 formatted timestamp */ > timestamp: string; > /** Float */ > amount: number; > segment_id: string; > reason: string; > } > | { > type: "prepaid_rollover"; > /** ISO-8601 formatted timestamp */ > timestamp: string; > /** Float */ > amount: number; > segment_id: string; > new_commit_id: string; > new_contract_id?: string; > } > | { > type: "prepaid_segment_expiration"; > /** ISO-8601 formatted timestamp */ > timestamp: string; > /** Float */ > amount: number; > segment_id: string; > } > | { > type: "credit_segment_start"; > /** ISO-8601 formatted timestamp */ > timestamp: string; > /** Float */ > amount: number; > segment_id: string; > } > | { > type: "credit_seat_based_adjustment"; > /** ISO-8601 formatted timestamp */ > timestamp: string; > /** Float */ > amount: number; > segment_id: string; > } > | { > type: "credit_automated_invoice_deduction"; > /** ISO-8601 formatted timestamp */ > timestamp: string; > /** Float */ > amount: number; > segment_id: string; > invoice_id: string; > contract_id: string; > } > | { > type: "credit_manual"; > /** ISO-8601 formatted timestamp */ > timestamp: string; > /** Float */ > amount: number; > segment_id: string; > reason: string; > } > | { > type: "credit_rollover"; > /** ISO-8601 formatted timestamp */ > timestamp: string; > /** Float */ > amount: number; > segment_id: string; > new_credit_id: string; > new_contract_id?: string; > } > | { > type: "credit_segment_expiration"; > /** ISO-8601 formatted timestamp */ > timestamp: string; > /** Float */ > amount: number; > segment_id: string; > }; > ``` > [accordion] contracts\_scheduled\_charges > > ### `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; > } > ``` > [accordion] contract\_hierarchy\_configurations > > ### `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. > [accordion] contracts\_overrides > > ### `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; > }; > ``` > [accordion] contracts\_transitions > > ### `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 | > [accordion] contracts\_edits > > ### `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 | > [accordion] contracts\_amendments > > ### `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. > [accordion] contracts\_rate\_cards > > ### `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 | > [accordion] contracts\_rate\_card\_entries > > ### `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 | > [accordion] contracts\_product\_list\_item\_versions > > ### `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. > [accordion] 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 | ## Alerts Includes alerts and the history of customer alerts triggered. > [accordion] alert > > ### `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. | > [accordion] customer\_alert\_history > > ### `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). > [!NOTE] > > **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). > [!NOTE] > > **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) | > [!NOTE] > > **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 | | Customers | [customer\_billing\_provider\_configuration](/guides/reporting-insights/data-export/database-reference#customer-billing-provider-configuration) | 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\_billing\_provider\_configuration\_schedule](/guides/reporting-insights/data-export/database-reference#contracts-billing-provider-configuration-schedule) | 2 hours | 4 hours | Incremental | | 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. > [!NOTE] > > **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. # 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://app.metronome.com/support). > [!NOTE] > > **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] > > **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://app.metronome.com/support) 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 > [!NOTE] > > In-app dashboards are currently in beta. Contact us via the [Metronome support portal](https://app.metronome.com/support) 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](https://mintcdn.com/metronome-b35a6a36/pUEKr5nqd5TnxR9X/images/docs/guides/reporting-insights/in-app-dashboard-screenshot.png?fit=max\&auto=format\&n=pUEKr5nqd5TnxR9X\&q=85\&s=79e2747ca5dcb288f833c5c451d2c6e8) **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.** > [!WARNING] > > **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://app.metronome.com/support). ## 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. > [!TIP] > > **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://app.metronome.com/support) 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://app.metronome.com/support) 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 a page of 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. ### Usage guidelines: - Pagination: Results are limited to 20 contracts per page; use 'cursor' for more ⚠️ 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 a page 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. Results are limited to 20 contracts per page. When the response includes a non-null `cursor`, pass it back as the `cursor` parameter to fetch the next page. # 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**. > [!WARNING] > > **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. > [!NOTE] > > Adding or updating custom fields on credits, commits, and contracts does not send `credit.edit`, `commit.edit`, or `contract.edit` lifecycle events. 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. # 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. > [!WARNING] > > **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: > [card] [Python](https://github.com/Metronome-Industries/metronome-python/blob/main/README.md) > [card] [Go](https://github.com/Metronome-Industries/metronome-go/blob/main/README.md) > [card] [Ruby](https://github.com/Metronome-Industries/metronome-ruby/blob/main/README.md) > [card] [Node.js](https://github.com/Metronome-Industries/metronome-node/blob/main/README.md) > [card] [Java](https://github.com/Metronome-Industries/metronome-java/blob/main/README.md) # Endpoints > [card] [Usage](/api-reference/usage/ingest-events) > > Send usage events from your application. > [card] [Billable Metrics](/api-reference/billable-metrics/create-a-billable-metric) > > Convert raw usage events into invoice quantities. > [card] [Products](/api-reference/products/create-a-product) > > Define line items on an invoice. > [card] [Rate cards](/api-reference/rate-cards/create-a-rate-card) > > Set your base prices. > [card] [Customers](/api-reference/customers/create-a-customer) > > Represent your customer relationships. > [card] [Contracts](/api-reference/contracts/create-a-contract) > > Define invoice behavior for a given customer. > [card] [Packages](/api-reference/contracts/create-a-package) > > Reusable, time-relative sets of contract terms. > [card] [Commits and Credits](/api-reference/credits-and-commits/create-a-commit) > > Modify invoice amounts. > [card] [Invoices](/api-reference/invoices/get-an-invoice) > > A set of charges for a single billing cycle. > [card] [Notifications](/api-reference/alerts/create-a-threshold-notification) > > Power workflows based on state from Metronome. # 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 } ``` > [!TIP] > > **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](https://mintcdn.com/metronome-b35a6a36/TrrblT2KR7zYyGbN/images/api-reference/import-open-apispec-in-postman-45a2b9a3f8d246e732acb56d86cf79c5.gif?s=f2d324581e0b1f70442d96a0632c5dd7) ### 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](https://mintcdn.com/metronome-b35a6a36/TrrblT2KR7zYyGbN/images/api-reference/bearer-token-f401b436bd13f7cdbd9b89035dcf20b0.png?fit=max\&auto=format\&n=TrrblT2KR7zYyGbN\&q=85\&s=91626cfff58745710ad6cca53db78956) 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](https://mintcdn.com/metronome-b35a6a36/TrrblT2KR7zYyGbN/images/api-reference/set-api-token-value-ae3df7105db46d195afa34e1f532aae1.gif?s=142a96bb94c0386e3544ce5c779fb23d) ### 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](https://mintcdn.com/metronome-b35a6a36/TrrblT2KR7zYyGbN/images/api-reference/auth-for-create-customer-38047e2b0b1c34b72f0f0803b20ff734.gif?s=c2381cc4aa01b306d54bd40719d20b2c) 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](https://mintcdn.com/metronome-b35a6a36/TrrblT2KR7zYyGbN/images/api-reference/sdks/sdk-view-event-73e1747ae1551477facc43cbc57b5d41.png?fit=max\&auto=format\&n=TrrblT2KR7zYyGbN\&q=85\&s=1513cdfb83df0156e8bf66f653f10e02) ## 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](https://mintcdn.com/metronome-b35a6a36/TrrblT2KR7zYyGbN/images/api-reference/sdks/sdk-billable-metric-548bf969fd6260246719c508d04edbbf.png?fit=max\&auto=format\&n=TrrblT2KR7zYyGbN\&q=85\&s=beaec32999ea48566c29221a15796773) 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](https://mintcdn.com/metronome-b35a6a36/TrrblT2KR7zYyGbN/images/api-reference/sdks/sdk-billable-metric-event-685727864059c82397e970c9313d34c3.png?fit=max\&auto=format\&n=TrrblT2KR7zYyGbN\&q=85\&s=d35de8d4067e32d4eaf2aed156c754f0) ## 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](https://mintcdn.com/metronome-b35a6a36/TrrblT2KR7zYyGbN/images/api-reference/sdks/sdk-customer-8951c5c90f6d572acfe0b66fb69c375a.png?fit=max\&auto=format\&n=TrrblT2KR7zYyGbN\&q=85\&s=b4d587d5569f286f4571a93ef13c238c) 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](https://mintcdn.com/metronome-b35a6a36/TrrblT2KR7zYyGbN/images/api-reference/sdks/sdk-billable-metric-customer-9c43209722c86ae10d972b5674713926.png?fit=max\&auto=format\&n=TrrblT2KR7zYyGbN\&q=85\&s=4f2af00f69f7d78e30885f4c25fb678f) ## 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](https://mintcdn.com/metronome-b35a6a36/TrrblT2KR7zYyGbN/images/api-reference/sdks/sdk-billable-metric-millions-19186d5f83b1cdad82704ab369e73138.png?fit=max\&auto=format\&n=TrrblT2KR7zYyGbN\&q=85\&s=1630f2d2105b45c00bf019065d697d1a) 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](https://mintcdn.com/metronome-b35a6a36/TrrblT2KR7zYyGbN/images/api-reference/sdks/sdk-contract1-1baf22de9680a77ea8381e4f6ac75422.png?fit=max\&auto=format\&n=TrrblT2KR7zYyGbN\&q=85\&s=7490b51331f5363a8798deb9404e0ac4) 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](https://mintcdn.com/metronome-b35a6a36/TrrblT2KR7zYyGbN/images/api-reference/sdks/sdk-contract2-e0955e079cd3ef6724b4770bc0227a10.png?fit=max\&auto=format\&n=TrrblT2KR7zYyGbN\&q=85\&s=7c92485534f8ed794cdc40f611230bf4) # 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" } ``` ## Common status codes 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 > [!NOTE] > > **NEED HELP?** > > If you encounter any issues with IP allowlisting or have questions about implementation, contact us via the [Metronome support portal](https://app.metronome.com/support). # 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" } ] ``` # Manage your support contact Source: https://docs.metronome.com/guides/platform-configuration/manage-support-contact Each Metronome account has one support contact. This is the person we'll reach out to about urgent account questions, API issues, escalations, and important support updates. You can find the current contact in **Settings > Team**. Look for the **Support contact** label next to their name. ## Change the support contact Account admins can choose a different active team member: 1. Go to **Settings > Team**. 2. Open the actions menu for the new contact. 3. Select **Set as support contact**. 4. Confirm the change. > [!NOTE] > > Your account must always have a support contact. Before deactivating the current contact, choose someone else to replace them. You cannot choose someone whose invitation is pending or whose account has been deactivated. # 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) > [!NOTE] > > Premium Data Export Tables may not all be currently available. Contact us via the [Metronome support portal](https://app.metronome.com/support) 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. > [!TIP] > > **CUSTOM ROLES** > > We also support custom roles, allowing you to tailor permissions to your needs. > > [Talk to an expert](https://metronome.com/talk-to-an-expert) ## Defined roles​ Metronome offers three out-of-the-box roles. Each role includes all access granted to the roles below it. * **Administrator**\ Ideal for project leads who need full functional access to oversee Metronome configuration and integration with other systems, along with administrative controls. Administrators have full CRUD (create, read, update, and delete) access to all components of the Metronome system. * **Writer**\ Ideal for members of the working team who are responsible for configuring and maintaining Metronome, including integrations with other systems. Writers have CRUD access to everything in Metronome except Metronome administrative settings, such as managing users, Metronome API tokens, outgoing webhooks, and data export. Writers can manage third-party integrations such as billing-provider and tax-provider settings. This access includes: * Creating, updating, and deleting billing-provider settings, and updating billing-provider configurations. * Setting billing-provider and tax-provider credentials, such as Stripe restricted keys and Anrok or Avalara credentials. * Setting the webhook secret Metronome uses to verify incoming Stripe webhooks. * Rotating Delta Stream signing secrets. * **Reader**\ Ideal for a non-acting member of the working team that is not involved with configuration, but needs access to Metronome data or is supporting the roll out of Metronome at your organization. Readers can view all components of the Metronome system, including settings and audit logs, but have no create, update, or delete access to any parts of the system. ## Set up RBAC​ RBAC policies are defined by your Identity Provider; you must set up [SSO](/guides/platform-configuration/single-sign-on-sso/). If no SSO is configured, all users with access to Metronome have full access permissions. To set up RBAC: 1. Set up [SSO](/guides/platform-configuration/single-sign-on-sso/). 2. With your Identity Provider, create a new claim to specify user roles.\ a. The claim can be called anything; we recommend `role`.\ b. The values for this claim are: `admin`, `writer`, `reader`, or any custom roles you work with the Metronome team to create. 3. Submit the new claim name via the [Metronome support portal](https://app.metronome.com/support). 4. Let us know via the [Metronome support portal](https://app.metronome.com/support) which role users should default to if not specified. By default, any user with no specified role is denied access to Metronome. ## Assign a role to an API token When creating a new API token in the Metronome UI, you can assign an RBAC role directly. The token will inherit the permissions of the selected role, scoping its access accordingly. Roles cannot be changed after a token is created. To assign a role to an API token: 1. In the Metronome UI, navigate to **Developer > API tokens**. 2. Click **+ Add**. 3. Select a role to assign to the token (**Administrator**, **Writer**, or **Reader**). 4. Complete token creation. > [!NOTE] > > To assign a custom role to an API token, contact us via the [Metronome support portal](https://app.metronome.com/support) to have the role created first. # Metronome's security principles Source: https://docs.metronome.com/guides/platform-configuration/security-principles Metronome is committed to security and keeping data safe—yours and your customers'. We adhere to industry-leading standards. We consistently review our security practices to ensure we have the right systems, policies, and controls in place. Our security practices are based on three core principles: * **Least privilege** No actor in Metronome has access to data or the ability to take actions until and unless that access has been explicitly granted. Access is controlled down to the field level. * **Zero-trust architecture** Metronome has been built from day one with zero-trust architecture. In practice, this means that any communication between two systems (or any actor and system) is authenticated. For example, a user communicating with the Metronome data layer must make requests with a security token in their request. The data layer may service that request by calling other services that subsequently call other services or databases, and so forth. The same security token must be passed on to each of these underlying calls, and each service in the stack uses the token to verify and grant the relevant access. Combined with the principle of least privilege, every single part of the Metronome product enforces that actors (human or system) can only access the most minimal data for their task. * **No access granted via long-lived credentials or configuration** Because of Metronome's zero-trust architecture, almost no part of Metronome's system depends on long-lived API keys or other such static security tokens. Our AWS organization is set up in such a way that we have no long-lived AWS credentials on developer's machines. Metronome engineers must mint new credentials each day, and those credentials last only 12 hours. For the most detailed and up-to-date information on security at Metronome, visit our [security page](https://metronome.com/company/security). To request a copy of our SOC 2 report, please contact your Metronome representative. # Single sign-on (SSO) Source: https://docs.metronome.com/guides/platform-configuration/single-sign-on-sso Single sign-on (SSO) allows team members to access Metronome with the same identity or service providers they use to authenticate within their own organization or external services. This means that your team can log into Metronome using your corporate sign-in process (for example, using a corporate Gmail account), instead of needing to create a new username and password. Metronome supports SSO with the [SAML 2.0](https://en.wikipedia.org/wiki/SAML_2.0) protocol, both for service provider and identity provider initiated authentication. This is supported by most common service provider and identity management services, including ADFS, Azure, Google, Okta, OneLogin, Ping Identity, and SecureAuth. Metronome SSO also handles user provisioning between your Identity Provider (IdP) and your Metronome instance. ## User management with SSO > [!NOTE] > > **REMOVE USERS** > > With SSO, access to Metronome is controlled by your identity provider. If a user is removed from Metronome access on your end, that user can no longer log in. Metronome still shows metadata about all users on the [Team Settings](https://app.metronome.com/settings/team) page, including the role each user had during their last log in. To set up SSO: 1. Request SSO via the [Metronome support portal](https://app.metronome.com/support). Metronome will provide you with these values: * Assertion Consumer Service (ACS) URL * Metronome Entity ID * Metronome logo (used for the tile within your identity provider) 2. Use these values to generate an Identity Provider URL (Single Sign-On Service URL) and an X509 signing certificate (in PEM or CER format). 3. Provide Metronome with the Identity Provider URL and X509 signing certificate. Metronome then creates a connection between your Identity Provider and the Metronome environment. 4. For the following attributes, provide Metronome with the equivalent attribute name in your claims: * `name` or `firstName lastName` * `email` 5. Once Metronome has the correct attribute mapping above, we conduct a few final tests with you to ensure SSO works. Once this has been verified your account will be switched over to SSO and your email domain is registered so that all logins route through your identity provider. ## Enforcing SSO Once you have SSO enabled, it is the only way to log in for anyone with an email address on your domain. Metronome registers your email domain as part of the cutover, so a user who tries to log in with a username and password is automatically redirected to your identity provider instead. Metronome also disables the manual creation of users when SSO is enabled, so every user is provisioned through your identity provider. If you need to grant access to people outside your domain—contractors, for example—submit a request via the [Metronome support portal](https://app.metronome.com/support) and we can leave manual user creation enabled for your account. # Set up webhooks Source: https://docs.metronome.com/guides/platform-configuration/webhooks/best-practices See [webhook types](/guides/platform-configuration/webhooks/webhook-types) for notification payloads. To inspect whether a notification was delivered, see [monitor webhooks](/guides/platform-configuration/webhooks/monitor-webhooks). ## Handle Webhook Notifications To receive Metronome webhooks, you need a webhook handler listening at a publicly accessible HTTPS URL that performs the below tasks. ### Acknowledge the Notification Upon receiving a notification, your endpoint must return a successful status code, such as `200 OK`. If Metronome receives a status code >`299`, notification retries are attempted until a successful status code is returned. If your webhook endpoint does not properly acknowledge the notification, Metronome continuously retries it with exponential backoff until it hits a 15-minute retry cadence. Once the retry process hits 15 minutes, Metronome repeats the notification until it is either accepted or two days have passed since the initial notification attempt (\~200 retries). It is recommended that you process webhooks asynchronously: store the webhook payload in a queue, return a `200` response code, and only then validate or process the payload. Removing webhook processing from the receiving path reduces the likelihood of your systems getting blocked. ### Prepare for Duplicate Notifications Under normal circumstances, Metronome sends each notification exactly once. However, there are a few situations that could cause you to receive the same notification multiple times: * **Retries** — As mentioned above, if Metronome receives an error when attempting to deliver the notification to your webhook handler, we retry the notification. Depending on the nature of the error, it's possible that your endpoint receives a notification without acknowledging it, in which case your endpoint receives the same notification again. * **Multiple webhook URLs** — If you configure Metronome to notify multiple webhook URLs, or even the same URL multiple times, notifications are sent multiple times. If you want to ensure duplicate notifications are ignored, you can use the notification's `id` field to deduplicate. ### Verify Notifications Because your webhook endpoint is a public URL, anyone could send a request to it. Before you take actions based on the notification, you should verify the information it contains. You can do this in two ways: by fetching data from the Metronome API yourself or by verifying the webhook request's signature. > [!NOTE] > > **INFO** > > Metronome may introduce backward-compatible changes to existing webhook shapes without notice, such as adding a new webhook field. Metronome recommends that you validate only fields that are expected to be present according to the documentation at time of integration. #### Call the Metronome API Webhook notifications contain only minimal information about the event that occurred. This means it's often useful to call the appropriate Metronome API endpoint to get the full details. For example, if you receive a webhook notification informing you that an invoice has been finalized, you can call the `/customers/{customer_id}/invoices/{invoice_id}` endpoint to fetch the details of the invoice mentioned in the notification. In this way, the notification serves as a hint that something has changed, but your code relies only on data obtained directly from the Metronome API. #### Verify Signatures If the above strategy doesn't work for your use case, Metronome also provides a method to verify the authenticity of notifications as you receive them by using the `Metronome-Webhook-Signature` HTTP header. The value of this header is a cryptographic signature of the HTTP request, using a secret key set up when you configure your webhook. > [!TIP] > > **Secret keys are unique per webhook** > > If you have multiple webhooks configured on your Metronome account, each webhook has its own secret key. To validate the signature, first concatenate the value of the request's `X-Metronome-Date` header and the exact bytes of the request body, separated by a newline character (`\n`). Then compute the HMAC-SHA256 of the resulting string, keyed by the webhook's secret key. Finally, compare the hexadecimal representation of the HMAC you computed with the one found in the `Metronome-Webhook-Signature` header. If they don't match, the webhook notification did not come from Metronome. ``` HMAC_SHA256(secret_key, X_METRONOME_DATE_HEADER + "\n" + BODY) ``` > [!TIP] > > **Use `X-Metronome-Date` instead of `Date`** > > Metronome sends both an `X-Metronome-Date` header and a standard `Date` header with the same value. Prefer `X-Metronome-Date` for signature verification: it's preserved end-to-end and isn't rewritten by intermediaries (load balancers, proxies, or frameworks) that may overwrite the standard `Date` header, which would otherwise cause signature verification to fail. The `Date` header is still supported for backward compatibility, but isn't recommended. The `X-Metronome-Date` header is included to aid in deduplication. You should ignore webhook requests that are older than five minutes, which means your webhook handler only needs to store recent notification IDs to prevent duplicates. > [!WARNING] > > **THE BODY MUST BE TREATED AS BYTES** > > When computing the signature, Metronome uses the exact bytes sent in the request body. Be careful to do the same in your code. If you try to use the parsed JSON body for verification purposes, you'll likely fail signature verification because serializing the data again is not guaranteed to produce the same JSON. The following code example shows how to perform signature validation: ```bash bash theme={null} echo -n "$X_METRONOME_DATE_HEADER\n$BODY" | openssl dgst -sha256 -hmac $KEY ``` ```javascript JavaScript theme={null} crypto .createHmac("sha256", KEY) .update(`${headers["X-Metronome-Date"]}\n${body}`) .digest("hex"); ``` ```go Go theme={null} func isSignatureValid(r *http.Request, body []byte, webhookSecret string) bool { signatureHeader := r.Header.Get("Metronome-Webhook-Signature") date := r.Header.Get("X-Metronome-Date") buff := bytes.NewBufferString(date) buff.WriteByte('\n') buff.Write(body) mac := hmac.New(sha256.New, []byte(webhookSecret)) mac.Write(buff.Bytes()) expectedMac := hex.EncodeToString(mac.Sum(nil)) if !hmac.Equal([]byte(expectedMac), []byte(signatureHeader)) { return false } return true } ``` To test this, consider the following example webhook notification. The secret key for verification is `correct-horse-battery-staple`: ```http theme={null} POST /webhook HTTP/1.1 Host: example.com User-Agent: Metronome Content-Type: application/json Date: Mon, 02 Jan 2006 22:04:05 GMT X-Metronome-Date: Mon, 02 Jan 2006 22:04:05 GMT Metronome-Webhook-Signature: b82652fa2246cf1d8a27e591f155c865f68b46c19b9213fd9c052f2419b4742b { "id": "b2c9e307-624e-4e7d-a5a4-1b74107d78c4", "type": "widget_created", "properties": { "customer_id": "5f794d50-085a-4db6-8d15-286e518b7225", "widget_id": "0891458d-b6f0-4fdd-a41e-380aae1a1e38" } } ``` ## Webhook IP Addresses Webhook notifications may come from the following IP addresses. This list may change, but if it does we'll give at least 30 days notice. ``` 52.39.198.29 44.241.254.184 52.42.224.184 52.89.217.131 44.231.139.128 54.245.125.92 3.134.178.31 3.12.62.53 3.140.90.67 3.142.231.113 3.131.206.70 3.132.225.181 ``` ## Send Webhooks to Slack If you want to receive Metronome notifications in Slack without building a custom webhook handler, you can configure Metronome to send notifications directly to a Slack channel. From there, you can triage and act on them. To send Metronome webhooks to Slack: 1. [Create an incoming webhook in Slack](https://api.slack.com/messaging/webhooks) and copy the generated webhook URL. It'll look something like: `https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX` 2. Create a webhook destination in Metronome for your Slack channel. In the Metronome app, go to **Developer** > **Notifications** > **Webhooks** > **Add** and paste your Slack webhook URL. 3. Set up a test notification to verify the integration. In the Metronome app, go to **Developer** > **Notifications** > **Create Notification** and create a notification like **Low credit balance reached**. 4. Verify the integration by testing the webhook connection. Trigger your test notification and check your Slack channel for a message from Metronome. When properly configured, you'll receive Slack messages that look like this: ```json 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" } ``` # Monitor your webhook integration Source: https://docs.metronome.com/guides/platform-configuration/webhooks/monitor-webhooks Metronome keeps webhook delivery history for the last 30 days. Review it in the app, or use the API to audit deliveries and debug failures. See [Set up webhooks](/guides/platform-configuration/webhooks/best-practices) for how your endpoint should acknowledge and verify notifications, and [webhook types](/guides/platform-configuration/webhooks/webhook-types) for payload shapes. ## How notifications are organized Delivery history is organized in four layers: * **Webhook destination.** The URL Metronome sends notification delivery attempts to. In the API, this is `webhook_id`. * **Notification configuration.** The rule that defines when a notification is triggered, for example, "Commit balance reaches \$5". For threshold alerts, the notification ID in the API is `alert_id`. System notifications do not have an ID since the rule is not configurable. * **Triggered notification.** A single instance when a notification triggers, for example, Customer A's balance reaches \$5. Customer B can trigger the same notification configuration at a separate time, which will result in a separate triggered notification. The triggered notification's `id` is the `id` field in the webhook payload Metronome sends. That ID stays the same on every delivery attempt for that firing. * **Delivery attempt.** One HTTP request to the webhook destination for that triggered notification. If the first attempt fails, Metronome retries, and each retry is another delivery attempt for the same triggered notification. ## Review deliveries in the app Metronome allows you to view the status of all webhook delivery attempts directly in the Metronome app. Go to **Developer** > **Notifications** > **Webhooks** and click into the specific webhook destination that you'd like to view all delivery attempts for. Filter by errors, customer, alert type, and more to build a deeper understanding of the system health of your Metronome webhook integration. ## List triggered notifications [List triggered notifications by webhook](/api-reference/webhooks/list-triggered-notifications-by-webhook) returns each triggered notification Metronome attempted to send to one webhook destination, with a summary of its delivery attempts. This can be used to understand the history of all triggered notifications for a specific webhook destination. Results are ordered by `first_attempted_at` descending. Each row is one triggered notification sent to that destination and includes: * `id` of the triggered notification. This is the `id` in the webhook payload, and it stays the same across delivery attempts. * `webhook_id`, the webhook destination * `customer_id`, which can be null for notifications that are not customer-specific * `notification_id`, the notification configuration. Null for system notifications, which have no configuration. * `notification_type`, this is `alert_type` for threshold notifications and `policy.type` for system and offset notifications. * `first_attempted_at` and `last_attempted_at` * `last_response_status_code`, from the latest delivery attempt * `num_attempts`, the latest number of delivery attempts for this triggered notification on this destination ## Get a triggered notification and its attempts Programmatically analyze a specific triggered notification further and understand the history of delivery attempts for that notification by using the API endpoint to [get triggered notification and delivery attempts](/api-reference/webhooks/get-triggered-notification-and-delivery-attempts). This returns the full payload of the notification as well as a timeline of delivery attempts to a specific webhook destination for that triggered notification. ## Debug a failed delivery 1. Call [list triggered notifications](/api-reference/webhooks/list-triggered-notifications-by-webhook) with the webhook destination, the time window, and filters for the customer or notification type you expect. 2. Find triggered notifications whose latest delivery attempt has a `last_response_status_code` outside 200–299, or whose `num_attempts` is greater than 1. 3. Call [get triggered notification and delivery attempts](/api-reference/webhooks/get-triggered-notification-and-delivery-attempts) with that triggered notification’s `id` to read the payload and each delivery attempt’s timestamp and status code. # Webhook types Source: https://docs.metronome.com/guides/platform-configuration/webhooks/webhook-types Metronome provides programmatic notifications in the form of webhooks. If you configure a webhook URL, Metronome sends an HTTP POST request to that URL when certain events occur, such as a contract being created, a threshold being reached or an invoice being finalized. Your service can then react to that notification by updating customer state, sending an email, or notifying internal users to take some action. For how to receive and verify notifications, see [Set up webhooks](/guides/platform-configuration/webhooks/best-practices). To inspect delivery history, see [monitor webhooks](/guides/platform-configuration/webhooks/monitor-webhooks). ## Webhook Types Metronome sends these webhook types: ### Threshold Notifications **`alerts.`** Threshold notifications monitor real-time metrics and trigger when defined thresholds are crossed. See our threshold notifications [documentation](/guides/customers-billing/set-up-notifications/threshold-notifications) for more on how to configure these types of notifications Threshold notifications have this structure: ```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" } ``` ### System and offset notifications **System notifications for contract, credit, commit, subscription, and invoice events** **`contract.`** **`commit.`** **`credit.`** **`subscription.`** **`invoice.void`** 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). See our system notifications [documentation](/guides/customers-billing/set-up-notifications/system-notifications) for more on how to configure these types of notification System notifications have this structure: ```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" } } ``` ```json subscription.create theme={null} { "id": "b7e2f1a4-3c5d-5e6f-8a9b-0c1d2e3f4a5b", "type": "subscription.create", "timestamp": "2026-10-01T15:30:00Z", "environment_type": "PRODUCTION", "subscription_id": "6a1f8c3e-2b4d-4e5f-9a7b-8c9d0e1f2a3b", "subscription_custom_fields": { "seat_type": "developer" }, "starting_at": "2026-11-01T00:00:00Z", "ending_before": null, "payment_gate_config": { "payment_gate_type": "STRIPE", "tax_type": "STRIPE" }, "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 subscription.start theme={null} { "id": "c8f3a2b5-4d6e-5f7a-9b0c-1d2e3f4a5b6c", "type": "subscription.start", "timestamp": "2026-11-01T00:00:00Z", "environment_type": "PRODUCTION", "subscription_id": "6a1f8c3e-2b4d-4e5f-9a7b-8c9d0e1f2a3b", "subscription_custom_fields": { "seat_type": "developer" }, "starting_at": "2026-11-01T00:00:00Z", "payment_gate_config": { "payment_gate_type": "STRIPE", "tax_type": "STRIPE" }, "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 subscription.end theme={null} { "id": "d9a4b3c6-5e7f-5a8b-9c1d-2e3f4a5b6c7d", "type": "subscription.end", "timestamp": "2027-01-01T00:00:00Z", "environment_type": "PRODUCTION", "subscription_id": "7b2a9d4f-3c5e-4f6a-8b9c-0d1e2f3a4b5c", "subscription_custom_fields": { "seat_type": "admin" }, "ending_before": "2027-01-01T00:00:00Z", "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 invoice.void theme={null} { "id": "38498915-c390-4c23-b13b-d6de5bfaadce", "type": "invoice.void", "timestamp": "2026-10-15T12:00:00Z", "environment_type": "PRODUCTION", "invoice_id": "958c06cf-dafb-4190-be8d-86f010f6bbe5", "invoice_type": "USAGE", "invoice_custom_fields": { "purchase_order": "PO-123" }, "contract_id": "4066aa52-4c2f-4145-9023-afe5fa7b4a62", "contract_custom_fields": { "plan": "enterprise" }, "customer_id": "cedde3ab-5bf2-4176-83a7-1767671ad514", "customer_custom_fields": { "region": "us-west" } } ``` **Offset notifications for contract, credit, commit, and subscription affiliated events** 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). See our offset notifications [documentation](/guides/customers-billing/set-up-notifications/offset-notifications) for more on how to configure these types of notification Offset notifications have this structure: ```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" // signed ISO-8601 duration } ``` **Invoice finalized notifications** **`invoice.finalized`** Triggered whenever an invoice is finalized (happens after the grace period). Invoice finalized notifications have this structure: ```json theme={null} { "id": "fc00bd44-8d4b-4913-9b7c-fd1f8da61e62", "properties": { "invoice_id": "de99894e-f9ce-4b6c-92b0-f4ec0d09b6f1", "customer_id": "3c9e87ba-0e49-44a3-9aa9-6917f8da3491", "invoice_finalized_date": "2024-02-20T15:50:07.457Z" }, "type": "invoice.finalized" } ``` > [!NOTE] > > **NOTIFICATION CONFIGURATION** > > Contact us via the [Metronome support portal](https://app.metronome.com/support) to set up `invoice.finalized` notifications. ### External notifications **Billing provider error notifications (Stripe)** **`invoice.billing_provider_error`** Billing provider error webhooks only apply to Stripe and are triggered any time there is an error in sending an invoice to Stripe (for example, the customer does not exist within Stripe or the customer does not have a valid payment method). No additional configuration is needed for this webhook; notifications are automatically sent when a webhook destination is set up and the Stripe integration is enabled on the account. Note that no Metronome webhook is triggered for errors residing entirely within Stripe (such as payment failures). Billing provider error notifications have this structure: ```json theme={null} { "id": "c941cccc-a890-45e4-96de-3fdb8a6809f3", "properties": { "invoice_id": "9927e175-c1d3-4f94-875b-8906bc773a95", "customer_id": "83518c41-76ff-4ac4-85d4-bd7010112bd3", "billing_provider": "STRIPE", "billing_provider_error": "No such customer: 'cus_PQzIVPOCGb4otV'" }, "type": "invoice.billing_provider_error" } ``` **Integration Issues** **`integration.issue`** Integration issue webhooks are triggered when there is an error with the client's third party integration (for example, invalid credentials, misconfigured connections, or API errors). No additional configuration is needed; notifications are automatically sent when a webhook destination is set up and the integration is enabled. Integration issue notifications have this structure: ```json theme={null} { "id": "c941cccc-a890-45e4-96de-3fdb8a6809f3", "type": "integration.issue", "properties": { "integration": "NETSUITE", "error": "Authentication failed: Invalid client credentials", "error_code": "INVALID_CREDENTIALS", "timestamp": "2025-10-03T12:34:56.789Z" } } ``` **AWS marketplace notifications** **`marketplaces.aws_metering_disabled`** Triggered when an AWS marketplace customer is disabled AWS marketplaces metering notifications have this structure: ```json theme={null} { "id": "daf54f25-12f4-4b2a-8462-ebfff4b622b7", "properties": { "customer_id": "4ffe51f1-3702-490c-816e-35fad3e271de", "aws_customer_id": "SJyeYLq7123", "aws_product_code": "6m81ochldaiejgnw0b8391bfn" }, "type": "marketplaces.aws_metering_disabled" } ``` **Azure marketplace notifications** **`marketplaces.azure_metering_disabled`** Triggered when an Azure marketplace customer is disabled Azure marketplaces metering notifications have this structure: ```json theme={null} { "id": "c9afa306-4449-45f3-9bce-68e4927a1f0b", "properties": { "customer_id": "1eea08e0-2fe0-45ad-96e2-3c1dbc2ce3a8", "subscription_id": "f6ccac8e-9918-4c8f-9597-8a210a84c31c" }, "type": "marketplaces.azure_metering_disabled" } ``` **GCP marketplace notifications** **`marketplaces.gcp_metering_disabled`** Triggered when a GCP marketplace customer is disabled GCP marketplaces metering notifications have this structure: ```json theme={null} { "id": "c9afa306-4449-45f3-9bce-68e4927a1f0b", "properties": { "customer_id": "1eea08e0-2fe0-45ad-96e2-3c1dbc2ce3a8", "gcp_usage_reporting_id": "project_number:012345678912", "gcp_entitlement_id": "f6ccac8e-9918-4c8f-9597-8a210a84c31c", "gcp_service_name": "your-listing.endpoints.provider.cloud.goog" }, "type": "marketplaces.gcp_metering_disabled" } ``` ### Payment gating notifications Payment gating notifications are tied to specific workflows in Metronome that gate access to some product (e.g. commit balance) based on successful payment collection. **Payment threshold reached** This webhook is fired when a payment gating action is triggered, such as when a customer hits their `threshold_amount` for Threshold Billing. **Payment gate status** After a payment is attempted for a payment gate workflow, this webhook returns the status. It includes relevant metadata from the gateway, such as error codes, if applicable. **Payment gate action required** This webhook is fired if an additional action is required to complete payment. It includes relevant metadata to identify the associated payment in the gateway, if applicable. **External workflow initiated** If processing payment via an external gateway outside of a native Metronome integration, this webhook will provide you the information to process that transaction. The `workflow_id` provided is used to release or cancel the balance, pending payment outcome. Payment gating notifications have this structure: > [accordion] Payment gate status > > ```json theme={null} > { > "id": "d304936c-a287-492c-b546-ac79dc673191", > "properties": { > "workflow_type": "manual_commit", > "customer_id": "6352d562-213f-4a6e-819f-58fdabc3f2b9", > "contract_id": "bbf87cf7-beaa-4d96-aea4-2cd87009dcb6", > "invoice_id": "6644b5ec-394a-4d07-a037-e2827a0af4be", > "payment_status": "failed", > "timestamp": "2025-01-01T00:00:00Z", > "error_message": "Your card has insufficient funds.", > "billing_provider": { > "type": "stripe", > "stripe": { > "payment_intent_id": "pi_3RP3ioIkTQSg6Mm31jR006rF", > "error": { > "type": "card_error", > "code": "card_declined", > "decline_code": "insufficient_funds", > "message": "Your card has insufficient funds." > }, > }, > }, > }, > "type": "payment_gate.payment_status" > } > ``` > [accordion] Payment gate action required > > ```json theme={null} > { > "id": "417fcaa4-f3cf-434e-ab20-f70204cfd5ef", > "properties": { > "workflow_type": "spend", > "customer_id": "d290dec8-4ebb-4e73-89ef-45ed3443ca67", > "contract_id": "80b07d70-c84e-4ff0-b42c-875defff0931", > "invoice_id": "dd864572-9787-573f-9c74-e5159b4ea97c", > "error_message": "three_d_secure_redirect", > "billing_provider": { > "type": "stripe", > "stripe": { > "payment_intent_id": "pi_3ROpJCIkTQSg6Mm31fNUnPKx", > }, > }, > }, > "type": "payment_gate.payment_pending_action_required" > } > ``` > [accordion] Threshold reached > > ```json theme={null} > { > "id": "417fcaa4-f3cf-434e-ab20-f70204cfd5ef", > "properties": { > "workflow_type": "spend", > "customer_id": "d290dec8-4ebb-4e73-89ef-45ed3443ca67", > "contract_id": "80b07d70-c84e-4ff0-b42c-875defff0931", > "timestamp": "2025-01-01T00:00:00.000Z", > }, > "type": "payment_gate.threshold_reached" > } > ``` > [accordion] External workflow initiated > > ```json theme={null} > { > "id": "417fcaa4-f3cf-434e-ab20-f70204cfd5ef", > "properties": { > "workflow_type": "spend", > "customer_id": "d290dec8-4ebb-4e73-89ef-45ed3443ca67", > "contract_id": "80b07d70-c84e-4ff0-b42c-875defff0931", > "workflow_id": "d7abd0cd-4ae9-4db7-8676-e986a4ebd8dc", > "invoice_id": "6a37bb88-8538-48c5-b37b-a41c836328bd", > "invoice_total": 1500, > "invoice_currency": "USD", > }, > "type": "payment_gate.external_initiate" > } > ``` # 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 > [!WARNING] > > **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 > [!NOTE] > > **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. > [!TIP] > > **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. > [!TIP] > > **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. > [!TIP] > > **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. > [!TIP] > > **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 > [!NOTE] > > **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. > [!TIP] > > **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). > [!TIP] > > **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. > [!TIP] > > **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 > [!NOTE] > > **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. > [!TIP] > > **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). > [!TIP] > > **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 > [!NOTE] > > 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. > [!NOTE] > > **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". > [!TIP] > > **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. > [!TIP] > > **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. > [!TIP] > > **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 > [!NOTE] > > **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. > [!TIP] > > **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. > [!TIP] > > **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. > [!TIP] > > **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 > [!TIP] > > **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 # Reconcile data Source: https://docs.metronome.com/guides/reporting-insights/financial-reporting/reconcile-data Data reconciliation is a key step in most finance workflows wherein you verify that two sets of records are in agreement for a given time period. These workflows typically occur when closing an accounting period, before revenue is recognized in downstream systems. Performing data reconciliation ensures that data is completely and accurately transmitted across systems. Further, the due diligence guarantees that you correctly invoice your customers and recognize the correct revenue. Given that Metronome stores all of your contract, usage, and pricing information, Metronome is uniquely suited to power this process. Your Metronome data can be reconciled against: * Salesforce * Stripe * Your own internal system * Third-party data warehouses Metronome provides two tools for performing data reconciliation: data exports and the API. ## Reconcile against data exports Metronome enables you to programmatically export your data to your existing data warehouse using [data export](/guides/reporting-insights/data-export). Data exports are a more efficient way to export larger quantities of data all at once, as opposed to repeatedly calling the API. The data exported from Metronome to your data warehouse can be queried to produce reports that compare an internal or external system to Metronome. A key part of enabling this comparison is foreign key mapping. Foreign keys enable you to map an entity in one system to another based on the primary keys in both tables. [Custom fields](/developer-resources/custom-fields/) provide the most common way to do this. Through foreign key mapping, you can compare whether a deal closed in SFDC exactly matches what's stored in Metronome. This includes things like the contract start and end dates, the commit amount, or custom negotiated discounts. You can also use data export to check that the finalized invoice amount in Metronome matches exactly what was invoiced with your invoice provider. Metronome's data export ensures that you have a reliable mechanism to receive all of your data and that it's structured in such a way that can be reconciled to the other systems that connect to Metronome. ## Data export reconciliation examples Imagine your organization uses Salesforce CPQ to store customer and deal information, Metronome for processing your usage based billing, and Stripe as your invoice provider. ![Data reconciliation workflow diagram](https://mintcdn.com/metronome-b35a6a36/TrrblT2KR7zYyGbN/images/docs/Invoices/data-rec-process-6f80e025db48f6dc8cc46fe923c5ad9f.png?fit=max\&auto=format\&n=TrrblT2KR7zYyGbN\&q=85\&s=3fb440126fe60c3e22765c77dcc179c1) As depicted above: * Salesforce and Metronome are integrated so that when a new customer and contract is created in Salesforce it is also created within Metronome. * Metronome begins metering the usage once the customer and contract is created from the Salesforce integration. At the end of the invoice period, Metronome sends the finalized invoices to Stripe so they can be billed to the end customer. * Additionally, Metronome regularly exports snapshots of data to your data warehouse for your reconciliation needs as covered below. ### Contract reconciliation To begin your data reconciliation, confirm that the customer and contract information in Metronome exactly matches what is contained within your Salesforce CPQ instance. Using Metronome's data exports, information like the start and end dates, commit details, and price overrides for your customers' contracts are exported directly to your data warehouse for you to cross check against SFDC. A common method that customers use to match the contract in Metronome to the corresponding contract in SFDC is to create a custom field on the contract that holds the SFDC opportunity ID. To verify that the Metronome contract information matches SFDC you would use a query like the following and match the SFDC opportunity ID stored as a custom field on the Metronome contract to the entry within your SFDC instance: ```sql theme={null} -- from the most recent view of your contracts, WITH max_contract_snapshot AS ( SELECT max(snapshot_id) AS max_snapshot_id FROM "contracts_contracts" ) -- find that contract by ID SELECT * FROM "contracts_contracts" WHERE id = '[insert Metronome contract id]' AND snapshot_id = (SELECT max_snapshot_id FROM max_contract_snapshot); ``` Similar to the example above, you also want to confirm that the commit created in Metronome matches the commit details that are stored within SFDC as part of your reconciliation flow. To find the contract's most recent commit information in Metronome (access schedule, invoice schedule, total amount) in data export, you would use a query like the following and again use the SFDC opportunity ID as the key to match on: ```sql theme={null} WITH max_commit_snapshot AS ( SELECT max(snapshot_id) AS max_snapshot_id FROM "contracts_commits" ) SELECT * FROM "contracts_commits" WHERE id = '[insert Metronome commit id]' AND snapshot_id = (SELECT max_snapshot_id FROM max_commit_snapshot); ``` Additionally, within SFDC, you may have custom terms that were negotiated with a customer that are represented in Metronome as contract overrides. As part of your reconciliation workflow, you want to crosscheck that the overrides created in Metronome match the custom terms that were entered within SFDC when the deal was closed. To find the current overrides on the contract in data export, you would use a query like the following and use the SFDC opportunity ID as the key to match on: ```sql theme={null} WITH max_overrides_snapshot AS ( SELECT max(snapshot_id) AS max_snapshot_id FROM "contracts_overrides" ) SELECT * FROM "contracts_overrides" WHERE contract_id = '[insert Metronome contract id]' AND snapshot_id = (SELECT max_snapshot_id FROM max_overrides_snapshot); ``` ### Invoice reconciliation Now that you have verified that the customer's contract information in Metronome matches what is in SFDC, you can move to the next step in your reconciliation workflows: reconciling finalized invoices in Metronome against Stripe. To reconcile the finalized invoices within Metronome, you would find the customer's most recent finalized invoice for the customer in data export using a query like the following and then match that to the record in Stripe to compare relevant details: ```sql theme={null} SELECT * FROM "invoice" WHERE customer_id = '[insert Metronome customer ID]' AND status = 'FINALIZED' ORDER BY end_timestamp DESC LIMIT 1; ``` ## Reconcile against the API Alternatively, you can power reconciliation workflows by pulling data from the Metronome API. The API allows you to query the common objects necessary for reconciliation—contracts, customers, invoices, and so on—through their LIST endpoints. Although Metronome suggests using Data Export for reconciliation, the API provides users with lower latency access to information. This enables business users to create real-time dashboards that highlight changes as you make them. # 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 > [!NOTE] > > **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](https://mintcdn.com/metronome-b35a6a36/TrrblT2KR7zYyGbN/images/docs/Invoices/rev-rec-model-29b0978437f475f196f6547b833ba134.png?fit=max\&auto=format\&n=TrrblT2KR7zYyGbN\&q=85\&s=29134d9f141a47dc97cc5606c28fc67a) ### 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 > [!NOTE] > > **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 # Get commit and usage analytics Source: https://docs.metronome.com/guides/reporting-insights/gtm-reporting/get-commit-and-usage-analytics This guide will walk you through building internal dashboards that empower your GTM teams to proactively monitor customer usage patterns and commit consumption, enabling timely interventions that prevent overspend surprises and improve customer retention. **Time to complete:** 2-3 hours for initial setup, plus ongoing refinement **Prerequisites:** * Data Export enabled and sending data to your internal warehouse or lakehouse * Access to business intelligence tool (e.g., Looker, PowerBI, Hex) with ability to query Metronome tables * At least one customer with an active commit **Key benefits:** * Prevent customer churn from unexpected overspend * Identify expansion opportunities from usage patterns * Enable proactive customer success engagement ## Before You Begin ### Required Access & Permissions **Role needed:** Admin or Analyst role in Metronome **Permissions:** * View customer contracts and commits * Access Data Export configurations * Create and schedule data exports **Data requirements:** At least 7 days of usage data for meaningful insights ### Understanding Your Data Metronome's [Data Export](/guides/reporting-insights/data-export) feature provides daily exports of Metronome data to your warehouse of choice. The data models include customer informatoin, granular usage and commit data, contract details, and more. ## Step-by-Step Implementation ### Step 1: Configure Data Export > [!NOTE] > > **PAID FEATURE** > > Data Export is a paid Metronome feature. Contact [solutions@metronome.com](mailto:solutions@metronome.com) to enable Data Export in your account. **Objective:** Set up automated data exports to feed your reporting dashboards **Instructions:** 1. Navigate to Developer > Data Export in the Metronome App 2. Click "Add Destination" 3. Configure your warehouse or lakehouse destination 4. Enable the following tables (note: clients may enable more than the following tables for additional use cases) * `customer` - All customers * `contracts` - All Contracts related data models (contact us via the [Metronome support portal](https://app.metronome.com/support) to enable) * `invoice` & `line_item` - All finalized invoices and line items * `draft_invoice` & `draft_line_item` - All draft invoices and line items **Expected result:** Data models correctly flowing into your destination warehouse or object storage on a daily basis. ### Step 2: Build Customer-level burn curve data models **Objective:** Build a per-customer commit burn curve with actual and expected burn over time **Instructions:** To create a commit burn rate curve, we need to combine 2 concepts, how much of a commit *should* be burned and how much of a commit has *actually been* burned. The following queries provide a step-by-step guide to define both concepts using Metronome data export data. > [!NOTE] > > **GENERALIZED SQL** > > The SQL used here is generalized SQL and will most likely not run in your query engine as-is. Python and SQL can both be used for the creation of these dashboards. 1. **Create pacing rate from `access_schedule` in the `contracts_balances` table:** The following query parses the access schedule JSON object from the `contracts_balances` table to generate the expected burn curve or how much of a commit *should* be burned at any given time. ```sql theme={null} /* ============================================================================== SAMPLE QUERY: ACCESS SCHEDULE ANALYSIS ============================================================================== Purpose: Analyzes access schedules by parsing JSON schedule data and calculating daily rates, total duration, and normalized balance types. Tables Required: - contracts_balances_table: Contains balance information with access_schedule JSON column ============================================================================== */ WITH access_schedules AS ( SELECT -- Extract schedule item details from JSON JSON_EXTRACT_SCALAR(schedule_item, '$.id') AS access_schedule_id, id AS balance_id, -- Convert amount from cents to currency units CAST(JSON_EXTRACT_SCALAR(schedule_item, '$.amount') AS DOUBLE) / 100 AS schedule_amount_usd, CAST(JSON_EXTRACT_SCALAR(schedule_item, '$.amount') AS DOUBLE) AS schedule_amount_cents, -- Parse ISO8601 timestamps to datetime and date JSON_EXTRACT_SCALAR(schedule_item, '$.date') AS schedule_start_datetime, JSON_EXTRACT_SCALAR(schedule_item, '$.end_date') AS schedule_end_datetime, CAST((JSON_EXTRACT_SCALAR(schedule_item, '$.date')) AS DATE) AS schedule_start_date, CAST((JSON_EXTRACT_SCALAR(schedule_item, '$.end_date')) AS DATE) AS schedule_end_date, FROM contracts_balances_table CROSS JOIN UNNEST( TRY_CAST( JSON_EXTRACT(JSON_PARSE(access_schedule), '$.schedule_items') AS ARRAY(JSON) ) ) AS schedule_items_table(schedule_item) ), schedule_duration AS ( SELECT access_schedule_id, -- Calculate total days in schedule (inclusive of start and end dates) DATE_DIFF('day', MIN(schedule_start_date), MAX(schedule_end_date)) + 1 AS total_schedule_days FROM access_schedules GROUP BY access_schedule_id ) SELECT -- Schedule details sch.access_schedule_id, sch.schedule_amount_usd, sch.schedule_amount_cents, sch.schedule_start_datetime, sch.schedule_end_datetime, sch.schedule_start_date, sch.schedule_end_date, -- Duration and rate calculations dur.total_schedule_days, sch.schedule_amount_usd / dur.total_schedule_days AS daily_rate_usd, -- Balance information bal.contract_id, bal.type AS original_balance_type, -- Normalized balance type with category CASE WHEN (bal.type = 'prepaid' AND JSON_ARRAY_LENGTH(JSON_EXTRACT(JSON_PARSE(bal.invoice_schedule), '$.schedule_items')) = 0) THEN CONCAT('free_commit') ELSE bal.type -- your metronome instance may have other balance types END AS normalized_balance_type, -- Invoice schedule metadata bal.invoice_schedule, JSON_ARRAY_LENGTH(JSON_EXTRACT(JSON_PARSE(bal.invoice_schedule), '$.schedule_items')) = 0 AS has_empty_invoice_schedule FROM access_schedules acs LEFT JOIN schedule_duration dur ON dur.access_schedule_id = acs.access_schedule_id LEFT JOIN balances_table bal ON acs.balance_id = bal.id ``` 2. **Calculate historical consumption using the invoice `line_item` table:** The following query parses invoice line item data to determine how much of the commit was *actually* burned in a given month. This query only parses finalized invoices and will later need to be joined against the draft invoice data to build an up to date view of the remaining commit. ```sql theme={null} /* ============================================================================== SAMPLE QUERY: FINALIZED INVOICE LINE ITEM ANALYSIS ============================================================================== Purpose: Analyzes finalized invoices and their line items to categorize spend types, calculate usage amounts, and identify commit vs on-demand usage patterns. Tables Required: - invoice_table: Contains invoice data with timestamps and status - line_item_table: Contains detailed line items linked to invoices - customer_table: Contains customer details Parameters to Replace: - {{line_item_types}} → comma-separated list of relevant line item types ============================================================================== */ WITH line_items AS ( SELECT li.* FROM line_items_table li INNER JOIN invoices_table inv ON li.invoice_id = inv.id AND inv.status = 'FINALIZED' -- Filter to finalized invoices only ) SELECT -- Date and time breakdowns CAST(inv.start_timestamp AS DATE) AS invoice_start_date, CAST(inv.end_timestamp AS DATE) AS invoice_end_date, DATE_TRUNC('month', inv.start_timestamp) AS invoice_start_month, -- Customer information inv.customer_id, cust.customer_name, -- Balance and commit tracking li.commit_id AS balance_id, li.commit_id IS NOT NULL AS is_burning_commit, -- Invoice details inv.id AS invoice_id, inv.issued_at AS invoice_issued_at, inv.status AS invoice_status, inv.billable_status AS invoice_billable_status, -- Line item details li.id AS invoice_line_item_id, li.product_id, li.name AS product_name, li.quantity AS line_item_quantity, li.unit_price AS line_item_price, li.total AS line_item_total_amount_cents, li.total / 100.0 AS line_item_total_amount_usd, li.commit_id IS NULL AS is_on_demand_usage, -- Audit timestamps inv.updated_at AS invoice_updated_at, li.updated_at AS line_items_updated_at, FROM invoices_table inv INNER JOIN line_items li ON inv.id = li.invoice_id AND li.line_item_type IN ({{line_item_types}}) -- Filter by Line Item Types that are appropriately contribute to Burn e.g., 'ContractUsageLineItem' LEFT JOIN customer_table cust ON cust.customer_id = inv.customer_id ``` 3. **Calculate current month consumption using the draft invoice `draft_line_item` table:** The previous query provides a historical month over month view of commit burn. The following query can be combined with the above to show how the commit has been burned as of the current day in the billing period. The query logic is similar to the finalized `line_item` pattern above, with the only difference being that it pulls intra-month commit data from the `draft_invoice` table. ```sql theme={null} /* ============================================================================== SAMPLE QUERY: DRAFT INVOICE LINE ITEM ANALYSIS ============================================================================== Purpose: Analyzes draft invoices and their line items to categorize spend types, calculate usage amounts, and identify commit vs on-demand usage patterns for the current, not finalized, billing period Tables Required: - draft_invoice_table: Contains draft invoice data with timestamps and status - draft_line_item_table: Contains detailed draft line items linked to invoices - customer_table: Contains customer details Parameters to Replace: - {{line_item_types}} → comma-separated list of relevant line item types ============================================================================== */ SELECT -- Date and time breakdowns CAST(drafts.breakdown_start_timestamp AS DATE) AS breakdown_start_date, CAST(drafts.breakdown_end_timestamp AS DATE) AS breakdown_end_date, DATE_TRUNC('month', drafts.breakdown_start_timestamp) AS breakdown_start_month, -- Customer information drafts.customer_id, cust.customer_name, -- Balance and commit tracking dli.commit_id AS balance_id, dli.commit_id IS NOT NULL AS is_burning_commit, dli.commit_segment_id, -- Invoice details drafts.invoice_id, drafts.issued_at AS invoice_issued_at, drafts.status AS invoice_status, drafts.billable_status AS invoice_billable_status, -- Line item details dli.id AS breakdown_line_item_id, dli.product_id, dli.name AS product_name, dli.quantity AS line_item_quantity, dli.unit_price AS line_item_price, dli.total AS line_item_total_amount, dli.total / 100.0 AS line_item_total_amount_usd, dli.commit_id IS NULL AS is_on_demand_usage, -- Audit timestamps drafts.updated_at AS invoice_updated_at, dli.updated_at AS line_items_updated_at FROM draft_invoice_table drafts INNER JOIN draft_line_item dli ON drafts.id = dli.invoice_breakdown_id AND dli.type IN ({{line_item_types}}) -- Filter by Line Item Types that are appropriately contribute to Burn e.g., 'ContractUsageLineItem' LEFT JOIN customer_table cust ON cust.customer_id = drafts.customer_id ``` 4. **Combine `access_schedule` , `line_item` , and `draft_line_item` query results and create a date spine:** There are many ways to achieve this in both SQL and python, and there are also many ways to group this data (i.e. account, industry type, etc), but the important things to flag are: * `line_item.commit_id` should be joined to `access_schedule.balance_id` * date\_spine should be created using the `schedule_start_date` and `schedule_end_date`, inclusive of the `schedule_start_date` so that consumption is only measured against the appropriate access schedule service period * when `line_item.commit_id` is null, this signifies on-demand usage, which can’t tie to a certain commit, thus this usage won’t show up in the burn curve * cumulative sums on `line_item_total_amount_usd` within an `access_schedule` service period will generate the total burn against a commit by the end of that service period * `forecast_burn_curve` can be modeled based on the heuristics of your choosing * the below is an example of what a commit burn rate dashboard could look like ![commit\_burn\_curve\_example\_chart](https://mintcdn.com/metronome-b35a6a36/yVlMhTemZHUzeXwH/images/docs/guides/implement-metronome/commit_burn_curve.png?fit=max\&auto=format\&n=yVlMhTemZHUzeXwH\&q=85\&s=19968d0a51dc3866f1cff11709a3c539) 5. **Flag over or under consuming customers:** Using the pacing curve and the actual burn curve, customers that are burning through their commits faster or slower than anticipated can be flagged. Many Metronome clients use this data to trigger early renewal conversations when a client is over consuming, or product activation conversations when a client is under consuming. A common pattern we’ve seen is to provide each Account Manager or CSM with a dashboard showing their assigned customers and the current state of consumption (over, under, on track). ## Understanding Your Results ### Interpreting the Data **What to look for:** * Steady, predictable usage patterns (healthy adoption) * Gradual usage increases (growing value realization) * Burn rates between 80-110% (on-track consumption) **Warning signs or concerning trends:** * Sudden usage spikes in first 30 days (potential misconfiguration) * Burn rate greater than 150% before month 3 (unsustainable consumption) * Repeated spike-and-drop patterns (unstable implementation) **Common patterns:** * **Pattern:** 300% burn rate in week 1 → **Action:** Immediate check-in call to review implementation * **Pattern:** Less than 50% burn rate after 60 days → **Action:** Success team to identify adoption blockers ## Best Practices & Tips ### Optimization Recommendations * **Frequency:** Review high-risk accounts daily, all accounts weekly * **Timing:** Metronome exports draft invoice data daily - it’s common for teams producing these dashboards to set SLAs by which their Account Management teams can expect to see fresh consumption data * **Audience:** CSM team primary, Sales team for expansion and net new opportunities ### Advanced Features * Predictive modeling using historical seasonal patterns * Multi-dimensional health scoring incorporating support tickets * Automated playbook triggers based on usage patterns ### Data Quality Considerations * Backdated usage can cause temporary spikes—wait 24 hours before escalating * Price changes mid-period may distort burn calculations * Always verify anomalies against recent configuration changes ## Integration & Next Steps ### Sharing & Distribution After the above metrics have been defined, there are many ways to operationalize the data. Included below are a handful of ideas we've seen Metronome clients deploy to help GTM teams prioritize customer reachouts and engagement. **Internal teams:** * Automated Slack posts for critical alerts * Weekly email digest to leadership with at-risk accounts * Real-time dashboard access for all customer-facing teams **External stakeholders:** * Monthly usage reports to customer admins * Quarterly business reviews with trend analysis ### Taking Action on Insights 1. **Overconsumption:** Schedule immediate call to review usage patterns and optimization opportunities 2. **Underconsumption:** Identify adoption barriers and offer implementation support 3. **Stable high usage:** Proactive expansion conversation before commit exhaustion ## Troubleshooting & FAQ ### Common Issues **Q: Why does my customer show 500% burn rate on day 2?** A: New customers often have initial configuration spikes as they're learning to use your platform. We recommend monitoring their usage in this critical period and providing onboarding/implementation guidance to avoid these early costly mistakes. **Q: Dashboard shows negative commit balance but customer hasn't been notified?** A: Metronome is a highly flexible system that allows for configurations which would result in negative usage. It’s important to ask your billing team for context if you see abnormal behavior in the commit burn curve visualizations. ### Data Discrepancy Checklist When report data doesn't match expectations: * ✓ Verify date ranges align with customer's billing period * ✓ Review for any backdated usage in past 48 hours * ✓ Validate commit terms match contract configuration in Metronome (start date, amount, duration) # Invoice with other systems Source: https://docs.metronome.com/integrations/invoice-integrations/custom-invoice-integrations This guide explores how to set up invoicing in systems not covered by Metronome’s native integrations. To support these workflows, you can collaborate with Metronome to create [data exports](/guides/reporting-insights/data-export/overview) or build a managed integration that connects to your billing system of choice. Managed integrations get built using the data export feature or Metronome APIs. ## Integration approach Often, out-of-the-box integrations to invoicing platforms don’t meet the core requirements of clients and require significant customization. This is because they focus on syncing data without considering the end-to-end use case and business model. In contrast, managed integrations with Metronome take a first-principles approach to meeting client invoicing requirements. As Metronome invests deeper into different business models, we continuously assess whether to build new native integrations to more billing platforms like our [Invoicing with Stripe](/integrations/invoice-integrations/stripe), [Invoicing with NetSuite](/integrations/invoice-integrations/netsuite), and [Invoicing with marketplaces](/integrations/marketplace-integrations/aws) solutions. For more information on how to set up a managed integration, contact [solutions@metronome.com](mailto:solutions@metronome.com). ## External billing provider setup This setup describes how you could send invoice data to external downstream billing providers using the Metronome API. While this example is specific to QuickBooks, the pattern and design decisions apply across other use cases. Before setting up in Metronome, check if your billing platform requires additional setup, such as organizational requirements or permissions to create invoices. For example, QuickBooks requires a Developer app to sync invoices: 1. **Create an Intuit Developer app.** Go to [developer.intuit.com](https://developer.intuit.com), create an app, and select the **Accounting** scope. 2. **Record your Client ID and Client Secret** from the app's Keys & Credentials page. 3. **Set a Redirect URI** for your OAuth callback endpoint. 4. **Complete the OAuth 2.0 flow** to obtain an access token and refresh token. 5. **Note your Realm ID** (Company ID) — this identifies which QBO company you're writing to. Once this setup is complete, proceed with the next steps. ### Configure required objects To support this use case, start by building out your customer and item objects inside of your selected billing system and store them in custom fields in Metronome. Learn more about how to use [custom fields](/api-reference/custom-fields). Recommended custom fields in Metronome: | Metronome entity | Custom field key | Value | | - | - | - | | Product | `qbo_item_id` | The QBO Item ID for this Metronome product | | Customer | `qbo_customer_id` | The QBO Customer ID for this Metronome customer | | Contract | `qbo_memo_ref` | Optional — reference to help link contracts to invoices in QBO | ### Customer mapping For each Metronome customer, either find or create a corresponding QBO Customer. The recommended approach is to store the QBO Customer ID as a custom field on the Metronome customer object (e.g., `qbo_customer_id`). If no match is found, create the customer in QBO and store the resulting QBO Customer ID back in Metronome as a custom field. ### Item mapping You have two strategies for mapping Metronome line items to QBO Items: | Strategy | How it works | Trade-offs | | - | - | - | | Per-product item | Create a QBO item for each Metronome product (e.g., "Warehouse Compute", "API Calls"). Map via `product_id`. | QBO reports break down revenue by product. Requires item governance and naming conventions. | | Single Item | Create one generic QBO item (e.g. “Metronome Usage”). All line items reference this one item. | Less detail in QBO reports (all revenue appears under one category). Simple and fast setup. | ### Integrate through the API Follow this recommended approach to push invoices to your downstream billing provider by building an integration on top of Metronome APIs: 1. Set up a [webhook endpoint](/guides/platform-configuration/webhooks/best-practices) and listen for the `invoice.finalized` event. This event gets created once an invoice is finalized in Metronome after the grace period ends. ```json theme={null} { "id": "f4988a54-effe-49a2-9a07-8adfedb7541c", "type": "invoice.finalized", "properties": { "invoice_id": "d23458e0-c9a0-5538-8e81-251835b9f57a", "customer_id": "e0ac4251-74f7-4040-a1bd-9d0ef0fbc5bc", "invoice_finalized_date": "2024-10-09T17:52:27.371Z" } } ``` > [!NOTE] > > **NOTE** > > The `invoice.finalized` event is not enabled by default for Metronome clients. To turn this event on, contact us via the [Metronome support portal](https://app.metronome.com/support). 2. This webhook provides `customer_id` and `invoice_id`. Use `customer_id` to query the `/listInvoices` endpoint for `finalized` invoices from the associated billing period. ```bash theme={null} curl -X GET https://api.metronome.com/v1/customers/e0ac4251-74f7-4040-a1bd-9d0ef0fbc5bc/invoices \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d "status=FINALIZED" \ -d "starting_on=2024-10-09T00:00:00.000Z" \ -d "ending_before=2024-10-10T00:00:00.000Z" ``` The response includes the full invoice objects with header-level fields (`id`, `status`, `total`, `subtotal`, `issued_at`, `start_timestamp`, `end_timestamp`, `contract_id`) and the `line_items` array with per-line details (`name`, `type`, `quantity`, `unit_price`, `total`, `product_id`, etc.). 3. Parse and transform the response into the appropriate format and upsert the invoice and line items. > [!NOTE] > > **NOTE** > > For QuickBooks, you need a customer and at least one item to exist. ### Transform and map fields This is the core of the integration — converting Metronome's invoice schema into expected formats for invoices. Below is an example mapping to QuickBooks fields. #### Invoice header mapping | Metronome field | QBO field | Notes | | - | - | - | | customer\_id | CustomerRef.value | Use your stored QBO Customer ID mapping | | issued\_at | TxnDate | Date portion only. Fall back to end\_timestamp if null | | invoice.id | DocNumber | QBO has a strict length limit. Use "MTR-" + first 8 chars of UUID | | end\_timestamp | DueDate | Or set a payment term (e.g. Net30) from the TxnDate | | (multiple) | PrivateNote | Store fields such as: full Invoice ID, status, billing period, contract ID, contract name | | (multiple) | CustomerMemo | Human-readable summary of the billing period and plan | #### Line item mapping | Metronome field | QBO field | Notes | | - | - | - | | line.name | SalesItemLineDetail.ItemRef | Map to your QBO Item (single or per-product) | | line.quantity | SalesItemLineDetail.Qty | Pass through directly | | line.unit\_price | SalesItemLineDetail.UnitPrice | Pass through directly | | line.total | Line.Amount | Check if amounts are in cents or dollars and convert accordingly | | (composite) | Line.Description | Include: line name, type, time window, pricing group values, product\_id | ### Create the invoice With all dependencies resolved and fields mapped, assemble and POST the invoice. In QuickBooks, the format looks like: ```http theme={null} POST /v3/company/{realmId}/invoice?minorversion=75 Authorization: Bearer {access_token} Content-Type: application/json { "CustomerRef": { "value": "{qbo_customer_id}" }, "TxnDate": "2026-03-01", "DocNumber": "MTR-EF9E4917", "PrivateNote": "Metronome invoice ef9e4917-... ", "Line": [ { "Amount": 7599.42, "DetailType": "SalesItemLineDetail", "Description": "Warehouse Compute (usage)...", "SalesItemLineDetail": { "ItemRef": { "value": "{qbo_item_id}" }, "Qty": 140.73, "UnitPrice": 54.00 } } ] } ``` ### Orchestration To build the necessary orchestration layer, you can choose to leverage existing developer environments or a third-party tool. If you’re investigating third-party tools, Metronome recommends using the IPaaS system Workato. Workato is an automation tool that enables organizations to transform and transmit data using point-and-click workflow building capabilities. Metronome published a [connector](/integrations/platform-integrations/workato-connector) in the Workato Public library, which acts as a wrapper to the Metronome API similar to an SDK. Leveraging these public connectors can accelerate the speed of development and provide additional clarity on how to interact with the distinct endpoints. For more information on integrating with the API or leveraging public connectors, contact us via the [Metronome support portal](https://app.metronome.com/support). # Integrate with NetSuite Source: https://docs.metronome.com/integrations/invoice-integrations/netsuite > [!NOTE] > > **Public Beta** > > Metronome's NetSuite integration is currently in a Public Beta. Breaking changes may occur between now and GA. > > Not all Metronome features are supported during Public Beta. Please contact us via the [Metronome support portal](https://app.metronome.com/support) if you have questions. > > Features known to be unsupported: > > * Custom currencies > * Account hierarchy Metronome's NetSuite integration enables clients to sync invoices and payments to NetSuite for two core use cases: * **Billing:** Send invoices to NetSuite for distribution and collection. * **Revenue recognition:** If a different system (e.g. Stripe) is used for billing, sync invoices and payment status to NetSuite to power revenue operations. ## NetSuite compatibility requirements The NetSuite integration is available to all Metronome customers, but it is designed to work with standard NetSuite configurations. NetSuite is highly customizable, and your instance may require some baseline configuration updates before the integration works out of the box. Before setting up the integration, confirm that your NetSuite instance meets the following requirements: * **Line item fields:** The line item `amount`, `quantity`, and `total` fields must be writable. * **Inventory items:** Inventory items that require a location are not supported. > [!NOTE] > > **SANDBOX VALIDATION** > > Before enabling the integration in production, validate the full invoice sync flow in your NetSuite sandbox environment. This helps surface any configuration issues before they affect live invoices. > [!NOTE] > > **THROUGHPUT** > > This integraion supports up to 25,000 arrears invoices/month. If your invoice volume exceeds this amount, data may take longer than expected to sync to NetSuite. > [!WARNING] > > **INSTANCE-SPECIFIC CUSTOMIZATIONS** > > Metronome does not modify the integration to accommodate custom NetSuite instance configurations. If your instance requires changes to be compatible, those updates will need to be made on your side. ## Connect Metronome to NetSuite To connect Metronome to NetSuite, navigate to the Metronome UI and go to the *Developer -> Integrations* tab. Select NetSuite from the options in *Available Integrations*. A pop-up will open that will provide instructions on how to connect Metronome with NetSuite. You will need to: * Provide Metronome with your NetSuite account ID * Download a permissions bundle (provided in the pop-up screen) to your NetSuite account, which will ensure Metronome has the appropriate permissions to write to and read from necessary objects in NetSuite * Provide Metronome with the generated credentials to access your NetSuite account Once complete, you should see NetSuite listed under the *Active Integrations* table. > [!NOTE] > > **INITIAL OBJECT SYNC** > > After creating the connection, it can take Metronome up to an hour to index objects inside of NetSuite. This may cause a delay in syncing invoices after initial set-up. ## Map your Metronome products to NetSuite items Metronome products map to NetSuite items, where the product id on the Metronome line item maps to an item id on the NetSuite invoice line. First create your items in NetSuite. You can map many Metronome products to a single NetSuite item. Once your NetSuite items are set up, follow the next steps * Create a custom field on the product object. Name it something like `netsuite_item_internal_id`. * For each product in Metronome, set the field with the corresponding internal item ID in NetSuite. * Use the edit mapping feature to set the relationship between the Metronome product custom field and the NetSuite item ID. Click on the NetSuite row in the **Active Integrations** table and select **Edit Mapping**. * The mapping should look like `Invoice.Items: internal_id -> ContractProduct: your key` ### Commit application for \$0 invoices If you operate a prepaid credit model and wish to send \$0 invoices to NetSuite to recognize revenue against consumption, you will need to create a "Commit Application" item in NS. For the \$0 invoices, the negative line items, which represent commit burn-down, will post against the commit application item. To set up: * Create the item in NetSuite. * Create a new custom field on the Metronome product. Name it something like `netsuite_commit_application_internal_id`. * On the prepaid commit product(s), set the value of the custom field to the internal id of the commit application product. * Using the entity mapping feature on the integrations table, create a new mapping for: `Invoice.items: commit_application_item_id -> ContractProduct: your key` This set up enables you to have different revenue treatments for the prepaid commit depending on whether the Metronome product is used for commit purchase (i.e. deferred revenue) or commit application (i.e. recognize revenue). > [!NOTE] > > **CHECK REVENUE CONFIGRUATION** > > In NetSuite, all items on an invoice must have the same revenue treatment. Meaning, they must all either defer or point to revenue. If your commit application item is set to defer revenue but usage items point to a revenue account, the invoice will fail to send to NetSuite. ## Configure your Metronome customer Create either billing or revenue system configurations on the Metronome customer object. Once created, these can then be referenced on the customer's contract to route contract invoices to NetSuite: * **Customer billing configuration:** For billing use cases, Metronome syncs the invoice to NetSuite once the invoice is finalized. NetSuite then handles invoice distribution, tax calculation, and payment collection. * **Revenue system configuration:** Metronome syncs invoices to NetSuite after payment has been attempted in a different system (e.g. Stripe). If payment was successful, Metronome will sync the associated payment information to NetSuite as a payment object. If payment fails upon first attempt but later succeeds, Metronome will create the payment object once successful. ### Set the customer billing configuration If a customer should be billed out of NetSuite, set the `customer_billing_configuration` as `netsuite`. This can either be done in the customer create call or after customer creation using the `/setCustomerBillingProviderConfigurations` end point or the UI. See example below: ```bash theme={null} curl https://api.metronome.com/v1/setCustomerBillingProviderConfigurations \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "data": [ { "customer_id": "4db51251-61de-4bfe-b9ce-495e244f3491", "billing_provider": "netsuite", "configuration": { "netsuite_customer_id": "58877111" }, "delivery_method_id": "5b95d955-b705-41c8-9d2e-34ccbdee5193" } ] }' ``` > [!NOTE] > > **SET CONFIGURATION ON CONTRACT** > > Metronome allows you to set multiple `customer_billing_configuration` per customer. Given this, once a `customer_billing_configuration` has been set, you must set the config on the relevant contract in order for Metronome to send the contract invoices to NetSuite. ### Set the revenue system configuration If the customer is billed outside of NetSuite, but NetSuite needs the invoice information for revenue recognition, set up a `revenue_system_configuration` for the customer via the API or UI. Metronome syncs both invoices and payments (if available) for contracts with a revenue system configuration. If payment fails for the invoice after the first attempt, Metronome will still sync the invoice to NetSuite as `OPEN`. If payment is reattempted later and succeeds, Metronome will retroactively update the associated invoice in NetSuite as 'PAID'. See an example below for setting the `revenue_system_configuration` via the `setCustomerRevenueSystemConfigurations` end point: ```bash theme={null} curl https://api.metronome.com/v1/setCustomerRevenueSystemConfigurations \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "data": [ { "customer_id": "7b8864ad-5238-4ec2-8b89-bee635e1876b", "provider": "netsuite", "configuration": { "netsuite_customer_id": "58771" }, "delivery_method_id": "6fe89b5a-41d0-413b-bb44-5f90522db8a2" } ] }' ``` > [!NOTE] > > **SET CONFIGURATION ON CONTRACT** > > Metronome allows you to set multiple `revenue_system_configuration` per customer. Given this, once a `revenue_system_configuration` has been set, you must set the config on the relevant contract in order for Metronome to send the contract invoices and associated payments to NetSuite. ### Provision the customer's contract Either the `customer_billing_configuration` or the `revenue_system_configuration` need to be set on a contract in order for Metronome to sync invoices to NetSuite. This provides you with flexibility to route invoices to different places on a per contract basis. Let's look at an example of a company: * All PLG customers are billed out of Stripe. These are self-serve customers that are charged a \$10 monthly subscription fee in return for 5 AI credits. * All SLG customers are billed out of NetSuite. These customers pay in quarterly installments for annual usage commitments. For PLG customers, I want Metronome to collect payment in Stripe and then sync the invoice to NetSuite. To enable this, there are two API calls I need to make to Metronome when a new PLG customer signs up: create a customer and create a contract. See example below for creating the customer object. This API call includes the creation of the `customer_billing_configuration`, and `revenue_system_configuration`: ```bash theme={null} curl https://api.metronome.com/v1/customers \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "ingest_aliases": [ "plgcustomer1@example.com" ], "name": "Customer 01", "customer_billing_provider_configurations": [ { "billing_provider": "stripe", "delivery_method": "direct_to_billing_provider",, "configuration": { "stripe_customer_id": "cus_123", "stripe_collection_method": "charge_automatically" } } ], "revenue_system_configuration": [ { "provider": "netsuite", "configuration": { "netsuite_customer_id": "58771" }, "delivery_method_id": "6fe89b5a-41d0-413b-bb44-5f90522db8a2" } ] }' ``` Next, see example below for creating the PLG contract for the customer with the `customer_billing_configuration` and `revenue_system_configuration` set on it. In order to get the `revenue_system_configuration_id` and `billing_provider_configuration_id`, you will need to call the fetch billing provider and revenue system configuration end-points: ```bash theme={null} curl https://api.metronome.com/v1/customers \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "4c09936b-455d-4c72-a120-d71b600a7546", "rate_card_id": "740a2ca1-64f6-417d-807a-05f154b3b1fe", "starting_at": "2025-06-01T00:00:00.000Z", "billing_provider_configuration": { "billing_provider_configuration_id": "e045c62b-65e7-4e84-a924-3f06f8b621d0" // UUID of previously created customer billing configuration }, "revenue_system_configuration": { "revenue_system_configuration_id": "d455j33b-12f7-4b76-a924-3f06f8b687q9" // UUID of previously created revenue system configuration }, "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": 1, "proration": { "invoice_behavior": "bill_on_next_collection_date", "is_prorated": true }, "subscription_rate": { "billing_frequency": "monthly", "product_id": "ed518bcb-acc1-4cd8-85dd-880c2eb38994" }, "description": "Basic tier", "name": "Basic Plan", "custom_fields": { "plan_tier": "basic" }, "temporary_id": "basic_plan_monthly" } ], "recurring_credits": [ { "access_amount": { "credit_type_id": "d3cb2827-dcb5-44af-9354-947a7197b9a6", "unit_price": 5 }, "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": "basic_plan_monthly", "apply_seat_increase_config": { "is_prorated": true } } } ] }' ``` For SLG customers, I want Metronome to sync the invoice to NetSuite where it can be billed. To enable this, the same API calls to create a PLG customer are required, but NetSuite should be created as a `customer_billing_configuration` on the customer and used as the billing config on the contract. ## Tax To calculate tax for invoices in NetSuite, you need to integrate NetSuite with your preferred tax provider. Metronome does not calculate nor sync tax amounts to NetSuite. The tax flow will look as follows: * Metronome creates an invoice in NetSuite. * Tax integration in NetSuite adds tax to invoice. This set-up is required regardless of whether you are using NetSuite for billing or just for revenue recognition. Note that tax is **not** synced back to Metronome. ## Manage the integration When Metronome sends invoices to NetSuite, it records information across four surface areas to help you manage state of each object and ensure all data is synced correctly: the UI, API, data export, and webhook notifications. Leverage this information to adjudicate potential sync issues and ensure all data successfully sends to NetSuite. ### Invoice state Metronome will record information in distinct places on the invoice object depending on whether NetSuite is configured as the `customer_billing_configuration` or the `revenue_system_configuration`. #### Successful syncs When NetSuite is set as the `customer_billing_configuration`, sync details will be stored in the `external_invoice` object. The invoice status will be reflected in the `external_status` property and the created NetSuite invoice id is stored oin the `external_invoice.invoice_id` property. See a /getInvoice example below: ```bash theme={null} curl https://api.metronome.com/v1/customers \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "id": "8f653259-640d-5a10-9636-2c7682a355fe", "start_timestamp": "2026-02-11T00:00:00+00:00", "end_timestamp": "2026-02-11T00:00:00+00:00", "issued_at": "2026-02-11T00:00:00+00:00", "customer_id": "43536714-7f62-4e27-abcd-492d231ab7a0", // ... "external_invoice": { "billing_provider_type": "netsuite", "invoice_id": "61112", // NetSuite invoice id "issued_at_timestamp": "2026-02-11T00:00:00+00:00", "external_status": "FINALIZED" // ... }' ``` Upon initial success, Metronome will emit a `invoice.invoice_sync_status` webhook notification providing the invoice details: ```json theme={null} { "id": "65472d2c-c51f-46b2-95b3-0eaeb5c3dc5a", "invoice_id": "a43c2489-3d2f-40a2-a469-16411c535406", "customer_id": "faeff926-0a94-45da-9048-5b9d381b608b", "contract_id": "dfaa1fd8-d4d7-42c0-b2ab-9cc532793ca7", "sync_type": "billing_provider, "external_invoice": { "billing_provider_type": "netsuite", "invoice_id": "9ae574fb-9d56-51c2-9077-b78971e9fe5b", // NetSuite invoice id "issued_at_timestamp": "2026-02-11T00:00:00+00:00", "external_status": "FINALIZED" // ... } } ``` If the invoice status changes in NetSuite, Metronome will update the `external_status` to reflect the new invoice state. Expect approximtely one-hour latency for these status updates. When NetSuite is set as the `revenue_system_configuration`, sync details will be stored in the `revenue_system_invoices` object on the invoice API. See example below: ```bash theme={null} curl https://api.metronome.com/v1/customers \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "id": "8f653259-640d-5a10-9636-2c7682a355fe", "start_timestamp": "2026-02-11T00:00:00+00:00", "end_timestamp": "2026-02-11T00:00:00+00:00", "issued_at": "2026-02-11T00:00:00+00:00", "customer_id": "43536714-7f62-4e27-abcd-492d231ab7a0", // ... "revenue_system_invoices": [ { "revenue_system_provider": "NETSUITE", "revenue_system_external_entity_id": "458886", "sync_status": "SUCCEEDED", "revenue_system_external_entity_type": "NETSUITE_INVOICE" } ] }' ``` Similarly, Metronome will emit a `invoice.invoice_sync_status` webhook notification with `sync_type` set to `revenue_system`. #### Sync failures When NetSuite is set as the `customer_billing_configuration`, `external_status` will be updated to `INVALID_REQUEST_ERROR` in the event of a failure. The error message will be stored in the `billing_provider_error` property. See a /getInvoice API example below: ```bash theme={null} curl https://api.metronome.com/v1/customers \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "id": "8f653259-640d-5a10-9636-2c7682a355fe", "start_timestamp": "2026-02-11T00:00:00+00:00", "end_timestamp": "2026-02-11T00:00:00+00:00", "issued_at": "2026-02-11T00:00:00+00:00", "customer_id": "43536714-7f62-4e27-abcd-492d231ab7a0", // ... "external_invoice": { "billing_provider_type": "netsuite", "external_status": "INVALID_REQUEST_ERROR", "billing_provider_error": "We've encountered the following error when trying to access the NetSuite API: Failed to create Netsuite Invoice object. No item id found 5551." }, // ... }' ``` When the error occurs, Metronome will emit a `invoice.invoice_sync_status` webhook notification providing the invoice details with associated error information. Clients should consume these webhooks to identify when an invoice fails to sync to NetSuite and adjudicate based on error details. In the example given above, the error message identifies that the item id for one of the Metronome products is incorrect. To address this problem, update the corresponding custom field with the correct NetSuite item id. Once fixed, you can reattempt the sync to NetSuite via the UI by clicking **Send to NetSuite** button on the invoice UI page. When NetSuite is set as the `revenue_system_configuration`, `sync_status` will be updated to `FAILED` in the event of a failure. The associated error for why the invoice failed will be stored in the `error_message` property. See example below: ```bash theme={null} curl https://api.metronome.com/v1/customers \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "id": "8f653259-640d-5a10-9636-2c7682a355fe", "start_timestamp": "2026-02-11T00:00:00+00:00", "end_timestamp": "2026-02-11T00:00:00+00:00", "issued_at": "2026-02-11T00:00:00+00:00", "customer_id": "43536714-7f62-4e27-abcd-492d231ab7a0", // ... "revenue_system_invoices": [ { "revenue_system_provider": "NETSUITE", "sync_status": "FAILED", "revenue_system_external_entity_type": "NETSUITE_INVOICE", "error_message": "We've encountered the following error when trying to access the NetSuite API: Failed to create Netsuite Invoice object. No item id found 5551." } ] }' ``` ### Payment state If Stripe is used for billing and NetSuite is configured as the revenue system, Metronome will first create an invoice object in Stripe. If the payment is successful: * Metronome will store the payment intent id and payment amount inside the `external_invoice` object in the `external_payment_id` and `invoiced_total` fields respectively. * When then syncing the invoice to NetSuite, Metronome will mark the invoice as `PAID` and create a linked payment object. Similar to the invoice sync, Metronome will emit a `payment.payment_status_sync` webhook notification to indicate success or failure of sending the payment object to NetSuite. If NetSuite is used for billing, Metronome will create an invoice in NetSuite. When that invoice is paid in NetSuite, Metronome will mark the invoice as `PAID` once data is synced back from NetSuite. ## Additional configurations ### Syncing custom fields Metronome also syncs additional metadata to the NetSuite invoice object to help with reconciliation workflows. To enable, create the following custom fields on your NetSuite invoice object with the following `id` (all case sensitive): * `metronome_invoice_id`: Metronome will store the associated Metronome `invoice_id` on this field. * `metronome_contract_id`: Metronome will store the associated Metronome `contract_id` on this field. * `metronome_customer_id`: Metronome will store the associated Metronome `customer_id` on this field. If these custom fields are not set-up, Metronome will be unable to sync the associated metadata. ### \$0 invoices By default, Metronome will send 0 USD invoices to NetSuite. These invoices can be used to track consumption against a commit or credit for revenue recognition. Make sure to set up the commit application item as described above if sending 0 USD invoices to NetSuite. Users can choose not to send these invoice by navigating to the *Developer -> Integrations* tab and clicking on the gear icon for the NetSuite connection. # Invoice with Stripe Source: https://docs.metronome.com/integrations/invoice-integrations/stripe Use Metronome’s native [Stripe](https://stripe.com/) integration to invoice your customers with Stripe. With the Stripe integration, when an invoice finalizes at the end of the billing period, Metronome automatically creates a corresponding invoice in Stripe to collect payment. Leveraging the advanced invoicing capabilities of Stripe helps you reduce your involuntary churn by maximizing your payment success rate for scenarios like pay-as-you-go customers. This guide describes how to set up Stripe as your external billing provider, interact with the integration, and understand how Metronome handles Stripe limits. ## Set up the Stripe integration​ Setting up the Stripe integration involves connecting Metronome and Stripe and configuring invoice settings. ### Connect Metronome and Stripe​ When you connect your Stripe account with Metronome, Metronome can automatically create invoices in Stripe. Connecting involves granting Metronome the permissions to write and read data on your behalf to your Stripe account. Clients commonly connect Stripe to Metronome production and sandbox environments. This enables them to test potential price changes or other invoice updates end-to-end before enabling them for production customers. When you set up the Stripe integration in Metronome Sandbox, Metronome automatically connects to your Stripe test mode so you can test your integration end-to-end with invoice creation and payment collection. To connect Metronome and Stripe: 1. Authenticate your Stripe account from Metronome. Go to [Developer - Integrations](https://app.metronome.com/settings/general/integrations) → click **Enable** and complete the Stripe wizard. 2. Set up a Stripe connection from each Metronome environment you want to send invoices through, like production and sandbox environments. 3. Enable Stripe's [automatic payment retry](https://stripe.com/docs/billing/revenue-recovery/smart-retries) capabilities to improve invoice payment success. ### Connecting Metronome to Multiple Stripe Accounts​ Metronome supports multi-entity billing with Stripe so you can connect your Metronome environment to many Stripe accounts. This feature enables complex enterprises to manage their billing and finances as distinct business units. To set up multiple Stripe accounts: 1. Go to **Developer - > Integrations** 2. Select **Stripe - > Add another** 3. Select the appropriate Stripe account Once complete, you will see a row in **Active Integrations** for each Stripe account that Metronome is connected to. You can create an alias for each account to identify them. For example: **Stripe NA** and **Stripe EU** . This alias will appear wherever the Stripe account is referenced in the Metronome App. > [!WARNING] > > **WARNING** > > If using multi-entity billing, you must use `delivery_method_id` when setting the customer billing configuration. Ensure that your customer sign-up flow uses this field before setting up multi-entity billing. See [set customer billing configuration](/integrations/invoice-integrations/stripe#set-the-customer-billing-configuration%E2%80%8B) for more details. ### Configure optional global integration settings available After connecting Metronome to Stripe, you have certain options that you can configure from the [General Settings - Integrations page](https://app.metronome.com/settings/general/integrations). If connected to multiple Stripe accounts, you will need to configure the settings for each account independently. | **Invoice settings** | | | - | - | | **Set invoice due date** | Stripe defaults to invoice due dates within 30 days after they're sent. You can change this option to a different value. This setting has no effect for customers configured to be charged automatically. | | **Leave invoices as drafts** | By default, Metronome sends all invoices to Stripe with the `auto_advance` option set to true allowing invoices to be finalized in Stripe immediately without any action required on your side. If you prefer to leave invoices as draft so you can review and finalize manually in Stripe, mark the "leave invoices as drafts" option in Metronome. Metronome sets the Stripe `auto_advance` to false. | | **Skip zero-total invoices** | If Stripe invoicing is enabled for a customer, all invoices finalized in Metronome are sent to Stripe by default. The "skip zero-total invoices" option limits this to only send non-zero invoice. Stripe [imposes limits](https://docs.stripe.com/currencies#minimum-and-maximum-charge-amounts) on the minimum charge amounts. For example, with USD currency, the minimum charge allowed is \$0.50. If you select "skip zero-total invoices," Metronome skips sending invoices to Stripe that fall below the minimum charge amount for the currency. | | **Align effective\_at with last day of period** | By default, Stripe populates the "Invoice Date" field on PDF invoices and `effective_at` in the API with the date the invoice is finalized. Use this setting to populate the `effective_at` field with the last date of the invoice's service period (like Oct 31 for an Oct 1-31 invoice). This can help ensure usage invoices are tracked against the correct accounting period, aligning with revenue recognition practices in downstream finance systems. \[!WARNING] This setting isn't supported with Stripe Tax due to a Stripe limitation that causes invoice syncing to fail. | | **Invoice Presentation** | | | - | - | | **Display line items with zero quantity on Stripe invoices** | If selected, Metronome creates a Stripe line item on the Stripe invoices for all charges, including the ones that have zero quantity. | | **Always display price and quantity information in Stripe invoice line item descriptions** | Because Stripe doesn't support decimal quantities, by default, Metronome displays quantities in line item descriptions if at least one quantity on an invoice is not an integer. By selecting "always display quantities in line items", quantities will always appear in line item names, regardless of whether the invoice has any non-integer quantities. | > [!NOTE] > > **INFO** > > These settings are enforced per Stripe account at the environment level. You cannot configure customer specific preferences. ### Create optional entity mapping rules By default, Metronome sets metadata on Stripe invoices objects that it creates. One item it sets is a `metronome_id`, which is the Metronome invoice ID that lets you map a Stripe invoice to its corresponding Metronome invoice. You may want to add additional metadata to Stripe entities. For example: * Add attributes like the contract name or contract ID to the Stripe invoice (visible to customers) by mapping Metronome contract or rate card custom fields to [Stripe invoice custom fields](https://docs.stripe.com/invoicing/customize#custom-fields). * Add metadata like invoice line item and invoice line item price objects to the Stripe invoice for your internal audits or for downstream integrations like tax calculation. To configure Metronome to automatically add your own additional metadata to Stripe entities, edit the Stripe integration mapping rules between Metronome custom fields and Stripe entities on the [General Settings - Integrations page](https://app.metronome.com/settings/general/integrations). **If connected to multiple Stripe accounts, you will need to configure each of these mappings individually.** **Assign line items to Stripe products example** A common use case for adding metadata to Stripe entities is assigning line items on a Metronome invoice to an existing product in Stripe. To do this: 1. Create a [custom field](/api-reference/custom-fields) key on the Metronome product entity: `stripe_product_id`. 2. Set the value for the custom field key you just created for each of your products in Metronome. 3. Go to the [General Settings - Integrations page](https://app.metronome.com/settings/general/integrations) and edit the mapping rules to map the Metronome custom field key `stripe_product_id` to Stripe `invoiceitem.price` . > [!WARNING] > > **Required for payment-gated commits** > > If you use [payment-gated commits](/guides/pricing-packaging/apply-credits-and-commits/manual-payment-gated-commits), every Metronome product used on a payment-gated commit **must** have a `stripe_product_id` custom field mapped to a valid Stripe Product ID. Without this mapping, Stripe cannot generate the invoice line item and the payment attempt will fail, voiding the commit. ![Stripe mapping](https://mintcdn.com/metronome-b35a6a36/_LXbywMyyxClBlP9/images/Integrations/stripe/invoice-stripe-mapping.png?fit=max\&auto=format\&n=_LXbywMyyxClBlP9\&q=85\&s=e32f1ed353b8bbebcac9603271725937) ### Set the customer billing configuration​ To determine which invoices to send to Stripe, Metronome looks at the `billing_configuration` for each customer. The `billing_configuration` is an object within the Metronome customer object that captures additional metadata necessary to support Metronome’s native integrations. This includes information like the billing provider `customer.id` and invoice preferences. If the customer’s `billing_configuration` is set to Stripe, a [Stripe invoice](https://stripe.com/docs/api/invoices) gets issued to the corresponding Stripe customer. Set the billing configuration for a customer in the [Metronome app](https://app.metronome.com/) or with the API. > [!NOTE] > > **INFO** > > If connected to multiple Stripe accounts, you can only set the billing configuration via the API. For the API, set this configuration during the customer creation process using the `/customers`endpoint or after the customer already exists with `/setCustomerBillingProviderConfigurations` [setting the billing configuration](/api-reference/customers/set-billing-provider-configurations-for-a-customer). To set the a billing configuration, Metronome requires you to either specify a `delivery_method` or `delivery_method_id`. If you are only connecting to a single Stripe account, use the `delivery_method`. If connecting to multiple Stripe accounts, you must use `delivery_method_id`. Metronome uses this ID to determine which Stripe account each invoice should be sent to. > [!NOTE] > > **INFO** > > You can find the `delivery_method_id` by using the `/listConfiguredBillingProviders` endpoint to fetch configured Stripe accounts in the Metronome environment. This example payload uses the `/customers` endpoint to set the billing configuration using `delivery_method`: ```bash theme={null} curl https://api.metronome.com/v1/customers \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "ingest_aliases": [ "team@example.com" ], "name": "Example, Inc.", "customer_billing_provider_configurations": [{ "billing_provider": "stripe", "configuration": { "stripe_customer_id": "cus_456", "stripe_collection_method": "charge_automatically" }, "delivery_method": "direct_to_billing_provider" }] }' ``` This next example payload uses the `/setCustomerBillingProviderConfigurations` to set the billing configuration of an existing client using `delivery_method_id`: ```bash theme={null} curl https://api.metronome.com/v1/setCustomerBillingProviderConfigurations \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "data": [ { "customer_id": "4db51251-61de-4bfe-b9ce-495e244f3491", "billing_provider": "stripe", "configuration": { "stripe_customer_id": "cus_1234", "stripe_collection_method": "charge_automatically" }, "delivery_method_id": "5b95d955-b705-41c8-9d2e-34ccbdee5193" } ] }' ``` The billing configuration consists of two fields that dictate how the Stripe invoice is created: * `stripe_customer_id`: The Stripe customer ID for the customer that gets issued a Stripe invoice. * `stripe_collection_method`: Determines how to collect payment for the customer. Stripe supports two [methods of collection](https://stripe.com/docs/api/invoices/object): * `charge_automatically`: Stripe attempts to charge for the invoice using the default payment method attached to the customer. > [!WARNING] > > `charge_automatically` requires a [default payment method](https://docs.stripe.com/api/customers/update#update_customer-invoice_settings-default_payment_method) to be set on the Stripe customer before the invoice is finalized. If no default payment method is configured, Stripe can't charge the invoice and payment will fail. Confirm the customer has a default payment method in Stripe before using this collection method. * `send_invoice`: Stripe emails this invoice to the customer with payment instructions. For the `send_invoice` option you must specify how many days a customer has until payment is due. This corresponds with the `days_until_due` field in the Stripe API. By default, Stripe invoices are due 30 days after creation. The Metronome API doesn't allow you to set this value directly, but you can update this setting on the [General Settings - Integrations page](https://app.metronome.com/settings/general/integrations). ### Set the contract billing configuration​ Metronome supports configuring the billing on the contract level. This allows you to optimize the billing for each contract: you may send pay-as-you-go contracts through Stripe but enterprise-level contracts through AWS. This example payload uses the `/contracts/create` endpoint to set the billing configuration: ```bash theme={null} curl https://api.metronome.com/v1/contracts/create \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "6ae46ff3-a73e-4553-a139-346eafcea608", "rate_card_id": "cfe45e46-0277-42e0-b66a-45ccbd028913", "starting_at": "2025-01-01T00:00:00.000Z", "billing_provider_configuration": { "billing_provider": "stripe", "delivery_method": "direct_to_billing_provider" } }' ``` If connected to multiple Stripe accounts, one customer may be mapped to multiple Stripe accounts. When creating the contract, use the `billing_configuration_id` which can be fetched from the `/getCustomerBillingProviderConfigurations` endpoint: ```bash theme={null} curl https://api.metronome.com/v1/contracts/create \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "customer_id": "6ae46ff3-a73e-4553-a139-346eafcea608", "rate_card_id": "cfe45e46-0277-42e0-b66a-45ccbd028913", "starting_at": "2025-01-01T00:00:00.000Z", "billing_provider_configuration": { "billing_provider_configuration_id": "561ea579-e830-41d9-9161-d35313c061c5" } }' ``` ### Adding a billing provider to an existing contract To add a billing provider configuration to an existing contract, use `add_billing_provider_configuration_update` on the `/v2/contracts/edit` endpoint. Its `schedule.effective_at` sets when the configuration takes effect: | `effective_at` | The configuration takes effect | | - | - | | `START_OF_CURRENT_PERIOD` | At the start of the contract's current billing period | | `START_OF_NEXT_PERIOD` | At the start of the contract's next billing period | | `TODAY` | At the start of the current day in UTC, or at the contract start if that's later | Each invoice belongs to the configuration in effect at the end of its service period. An invoice with no service period, such as a scheduled invoice, belongs to the configuration in effect on its issue date. If the edit makes invoices that already finalized belong to the new configuration, Metronome sends them to Stripe shortly after you make the edit. Invoices that finalize later are sent when they finalize. Metronome doesn't resend an invoice that's already in Stripe or that another billing provider already holds. For example, a monthly contract gets a Stripe configuration with `START_OF_CURRENT_PERIOD` partway through April: | Date | Event | | - | - | | Jan 1 | Contract starts | | Apr 1 | March usage invoice (service period Mar 1–31) finalizes, and a scheduled invoice is issued | | Apr 15 | Configuration added to the contract, effective Apr 1. **The Apr 1 scheduled invoice is sent to Stripe.** The March usage invoice isn't, because its service period ended before the configuration took effect. | | **May 1** | **April usage invoice finalizes and is sent to Stripe** | With `TODAY` on Apr 15, the configuration takes effect at the start of the current day in UTC (00:00 UTC on Apr 15), or at the contract start if that's later. Invoices with a service period are matched by the end of the service period, which is exclusive; others are matched by their issue date. So the Apr 1 scheduled invoice isn't sent, a scheduled invoice issued on Apr 15 is, and the April usage invoice is still sent on May 1. > [!NOTE] > > You can't add a billing provider configuration to an archived contract or to a contract that has already ended. ## Interact with the Stripe integration​ After connecting Stripe with Metronome, use the Metronome API and app to interact with your integration. ### Track Stripe invoice statuses in Metronome​ Metronome captures Stripe webhook events when the status of an invoice changes. The Stripe invoices statuses are accessible in Metronome as part of the response when fetching invoices from the [list invoices](/api-reference/invoices/list-invoices) API endpoint. ```json theme={null} { "id": "INVOICE_ID", ... "external_invoice": { "billing_provider_type": "stripe", "invoice_id": "in_123", "issued_at_timestamp": "2024-09-30T16:40:40.30184+00:00", "external_status": "PAID" }, ... } ``` These statuses are accessible in your data warehouse through the Metronome [data export](/guides/reporting-insights/data-export). They include: | **Stripe Webhook Event** | **external\_status in Metronome** | | - | - | | [invoice.finalized](https://stripe.com/docs/api/events/types#event_types-invoice.finalized) | FINALIZED | | [invoice.marked\_uncollectible](https://stripe.com/docs/api/events/types#event_types-invoice.marked_uncollectible) | UNCOLLECTIBLE | | [invoice.paid](https://stripe.com/docs/api/events/types#event_types-invoice.paid) | PAID | | [invoice.payment\_failed](https://stripe.com/docs/api/events/types#event_types-invoice.payment_failed) | PAYMENT\_FAILED | | [invoice.payment\_succeeded](https://stripe.com/docs/api/events/types#event_types-invoice.payment_succeeded) | PAID | | [invoice.voided](https://stripe.com/docs/api/events/types#event_types-invoice.voided) | VOID | | [invoice.deleted](https://stripe.com/docs/api/events/types#event_types-invoiceitem.deleted) | DELETED | > [!NOTE] > > **INFO** > > If the global configuration is set to `Leave invoices as drafts`, Stripe does not return a status and you won't see a Stripe invoice status in Metronome. ### Calculate dynamic sales tax Metronome’s native Stripe integration supports Anrok, Avalara, and Stripe Tax providers to add tax to an invoice created in Stripe. Which one you use depends on your invoice provider and compliance needs: | Provider | Invoicing integration | | - | - | | [Stripe Tax](https://docs.stripe.com/tax/set-up) | Yes | | [Anrok](https://www.anrok.com/integrations/stripe) | Yes (through [Stripe app](https://marketplace.stripe.com/apps/anrok)) | | [Avalara](https://www.avalara.com/us/en/products/integrations/stripe-invoicing.html) | Yes (through [Stripe app](https://marketplace.stripe.com/apps/avalara-avatax)) | Regardless of which provider you choose, the general flow when using Stripe invoicing is: 1. Metronome usage statement finalizes, creating a corresponding draft invoice in Stripe. 2. Metronome passes entity mapping data (product IDs, metadata) to the Stripe invoice. 3. Your tax provider calculates tax on the Stripe invoice. 4. The invoice is finalized in Stripe with tax included. For setup instructions, see the dedicated guide for your provider: [Stripe Tax](/integrations/tax-integrations/stripe-tax), [Anrok](/integrations/tax-integrations/anrok), or [Avalara](/integrations/tax-integrations/avalara). When integrating with Avalara or Anrok directly through Stripe (not via a Stripe app), Metronome allows up to one hour by default for tax to be applied to draft invoices before finalizing. Note that after one hour, the invoice is finalized in Stripe. If you prefer to keep these invoices in a draft state indefinitely, enable the "[Leave invoices as drafts](/integrations/invoice-integrations/stripe#configure-optional-global-integration-settings-available)" option in your Stripe integration settings. If you use a tax provider not listed above, or if you’re not using Stripe for invoicing, contact us via the [Metronome support portal](https://app.metronome.com/support) for guidance on configuring tax. ### Payment timing for `charge_automatically` invoices​ Metronome finalizes invoices immediately at the end of the billing period — there is no wait before the invoice is sent to Stripe. However, when Metronome sends a finalized invoice to Stripe with `charge_automatically`, Stripe waits **up to one hour** after delivering the `invoice.created` webhook before attempting payment. The invoice sits in `open` state during that window. This delay is a Stripe-side behavior that applies specifically to invoices that are manually finalized through the API (which is how Metronome submits all invoices today). It is not configurable in the Stripe Dashboard — the "grace period" setting in Stripe only controls the draft → finalized transition, not the finalized → payment-attempted transition. This delay does **not** apply to: * [Auto-recharge invoices](/guides/customers-billing/optimize-customer-experience/auto-recharge-options). * [Payment-gated commits](/guides/pricing-packaging/apply-credits-and-commits/manual-payment-gated-commits), where payment is collected manually. **If you see delays longer than an hour:** Stripe falls back to a **72-hour** wait when the `invoice.created` webhook delivery fails. If invoices are sitting in `open` well past an hour, check that your Stripe webhook endpoint is configured correctly and is returning a 2xx response. **Workaround to bypass the one-hour wait:** Confirm the payment intent yourself immediately after the invoice is finalized: 1. Listen for the Stripe `invoice.finalized` or `payment_intent.created` webhook. 2. Extract the `payment_intent` ID from the event payload. 3. Call [`POST /v1/payment_intents/:id/confirm`](https://docs.stripe.com/api/payment_intents/confirm) on the Stripe API. This reduces the time between finalization and payment attempt to a few seconds. ### Listen for Errors​ Invoicing errors can happen. For example, errors happen when Stripe customers don’t exist. To receive notifications from Metronome when an error sending an invoice to Stripe occurs, listen for the [webhook](/guides/platform-configuration/webhooks/webhook-types#webhook-types) type `invoice.billing_provider_error` . When receiving those webhooks, trigger internal notifications and actions to ensure proper invoicing of your customers. ## How Metronome handles Stripe limitations​ Stripe enforces certain limits on invoices that may cause discrepancies or issues when billing customers. This table describes how Metronome handles these limitations. | Stripe limitation | Metronome approach | | - | - | | **Stripe does not support decimal quantities** | If the quantity is a decimal for at least one line item on the invoice, Metronome sets the quantity as 1 for all the Stripe line items on the invoice. Metronome and provides the true quantity as part of each line item description. | | **Stripe imposes a maximum of 250 line items on their invoices** | If a customer invoice in Metronome exceeds 250 line items, the invoice is collapsed into one line item, labeled with your company name and the invoice total as the associated price. Provide full invoice visibility (with all line items) to your customers with [dashboards](/guides/customers-billing/optimize-customer-experience/customer-dashboards-and-reporting) that expose invoices in your UI. | | **Stripe does not allow a charge above 999,999.99 USD** | Metronome generates an error when creating an invoice with an amount above the Stripe maximum. Contact your Stripe representative and use the [Metronome support portal](https://app.metronome.com/support) to increase the limit if you need invoices with amounts above \$999,999.99. | | **No native support for issuing credit memos with Metronome** | The Metronome integration does not natively support issuing credit memos in Stripe. Learn more how to [issue credit memos](/guides/invoices/invoice-optimization/issue-credit-memos). | # Invoice with AWS Source: https://docs.metronome.com/integrations/marketplace-integrations/aws This guide describes how to enable Metronome to invoice on your behalf through AWS Marketplace. ## Create an AWS Marketplace listing​ 1. To gain access to the [AWS marketplace management portal](https://aws.amazon.com/marketplace/management/products/saas), you must be [an approved seller by AWS](https://aws.amazon.com/blogs/awsmarketplace/checklist-successfully-registering-seller-aws-marketplace/). 2. Complete **Step 1: Provide product information** and **Step 2: Configure fulfillment options** in the Product Creation Wizard. Metronome does not require specific inputs for these steps, however, you should be aware of the marketplace requirements to post and fulfill your offering. 3. Choose the **Pricing model** for your offering and select **Units** as the **Dimension unit type**. Metronome supports **Contract with Consumption** or **Usage-based pricing** options. This choice will be tied to the sales motion of your product: **Contract with Consumption** will have fixed-term lengths while **Usage-based pricing** products can be started or stopped at any time by your customer. You will need to know the product type when configuring the customer in Metronome. ![AWS product pricing options](https://mintcdn.com/metronome-b35a6a36/TrrblT2KR7zYyGbN/images/Integrations/aws/aws-product-pricing-options-800cc2b7159425ba9757416020e31e6c.png?fit=max\&auto=format\&n=TrrblT2KR7zYyGbN\&q=85\&s=c05e6087256662764fda91e9b32efc3e) 4. For products that use the **Contract with Consumption** model create one or more **Contract dimensions** tied to the sales motions of your product. These dimensions should correspond to the the different pricing models you have set up in Metronome. They will also be used to manage customer lifecycle events such as subscription end and renewal. This step is not required for **Usage-based pricing** products. * **Activate pay-as-you-go pricing for additional usage** should be unchecked for all dimensions. * You can select any values you prefer for the **API identifier** and **Display name**. ![AWS contract dimensions](https://mintcdn.com/metronome-b35a6a36/TrrblT2KR7zYyGbN/images/Integrations/aws/aws-contract-dimensions-f692b9c2f799e8ab42b1f4fb071a2642.png?fit=max\&auto=format\&n=TrrblT2KR7zYyGbN\&q=85\&s=531b73a614211a64a9ccc10f2d4821db) 5. Create a single **Usage dimension**. > [!WARNING] > > **CAUTION** > > The API identifier must be called `usage_fee` for the integration to work correctly. ![AWS usage dimension](https://mintcdn.com/metronome-b35a6a36/TrrblT2KR7zYyGbN/images/Integrations/aws/aws-usage-dimensions-8b98dbe02a3baced0080222245f6201f.png?fit=max\&auto=format\&n=TrrblT2KR7zYyGbN\&q=85\&s=059515412340be3fad194c6630cd0c1e) 6. For products that use the **Contract with Consumption** model, select **Single dimension per contract**. This step is not required for **Usage-based pricing** products. * For **Contract duration options** , select the duration that best applies to your product. ![AWS purchasing options](https://mintcdn.com/metronome-b35a6a36/TrrblT2KR7zYyGbN/images/Integrations/aws/aws-purchasing-options-5d582790c573b9b9474c46abd52335bc.png?fit=max\&auto=format\&n=TrrblT2KR7zYyGbN\&q=85\&s=5cb72111a0dec5c3dce4afd06f6664d0) 7. When setting up pricing for your listing, set the price for **all contract dimensions** to \$0. * For the single `usage_fee` dimension, set the price to \$0.01 per unit. > [!WARNING] > > **CAUTION** > > Deviating from these values will cause the integration to fail. ## Set up IAM credentials for Metronome to meter on your behalf​ To make API calls to AWS on your behalf, Metronome needs a role with the right permissions. To set up IAM credentials for Metronome: 1. In AWS, go to the AWS [policy creator](https://console.aws.amazon.com/iam/home?#/policies\$new?step=edit). 2. Create a policy and give it a meaningful name, like `MetronomeMarketplacePermissions`. 3. Specify these permissions: ```json theme={null} { "Version": "2012-10-17", "Statement": [ { "Action": [ "aws-marketplace:BatchMeterUsage", "aws-marketplace:GetEntitlements", "aws-marketplace:ListEntities", "aws-marketplace:DescribeEntity" ], "Effect": "Allow", "Resource": "*" } ] } ``` ![AWS policy](https://mintcdn.com/metronome-b35a6a36/TrrblT2KR7zYyGbN/images/Integrations/aws/aws-create-policy-8ed3b3fd1694aba513fb90ab1cecf8fc.png?fit=max\&auto=format\&n=TrrblT2KR7zYyGbN\&q=85\&s=c54e92adc76d9183d97254353e1b9217) 4. In Metronome, go to **Developer** > **Integrations** > **Available Integrations** > **AWS Marketplace** > click **Get started.** 5. Copy Metronome's AWS account ID and the unique external ID generated on step 1 of the menu. ![AWS external ID](https://mintcdn.com/metronome-b35a6a36/TrrblT2KR7zYyGbN/images/Integrations/aws/aws-external-id-bd81e1d60276843a029a395e1a046fd8.png?fit=max\&auto=format\&n=TrrblT2KR7zYyGbN\&q=85\&s=11258aa19906b9d9435eca8bec4afbd2) 6. Back in AWS, configure the new AWS role. \
    * Go to the [role creator](https://console.aws.amazon.com/iam/home?#/roles\\$new?step=type\\&roleType=crossAccount) > **Another AWS account**. \* Enter Metronome's AWS account ID and the unique external ID copied from the above step in the `External ID` field. \* Leave **Require MFA** unchecked.
![AWS role](https://mintcdn.com/metronome-b35a6a36/TrrblT2KR7zYyGbN/images/Integrations/aws/aws-create-role-67016e481011737dea91c599faf1aaee.png?fit=max\&auto=format\&n=TrrblT2KR7zYyGbN\&q=85\&s=f83da4be7c9a6ff0369252a363da3f20) 7. Click **Next: Permissions** , and under **Attach permissions policies** , attach the policy you created in step 2. ![AWS permissions](https://mintcdn.com/metronome-b35a6a36/TrrblT2KR7zYyGbN/images/Integrations/aws/aws-create-permissions-9dbc7c3e9f3d3bf38907454363eecbdf.png?fit=max\&auto=format\&n=TrrblT2KR7zYyGbN\&q=85\&s=42316a328b827d148f7b49ccb45a3fbc) 8. Click **Next: Tags** and add any desired tags. Tags are optional; your AWS Marketplace integration with Metronome works without them. 9. Click **Next: Review** and name the role `metronome-marketplace`. > [!WARNING] > > **CAUTION** > > The role name **must** begin with `metronome-marketplace`. To assign different roles for different environments, consider naming those roles something like `metronome-marketplace-production`, `metronome-marketplace-staging`. ![AWS review](https://mintcdn.com/metronome-b35a6a36/TrrblT2KR7zYyGbN/images/Integrations/aws/aws-review-995fe39a230a67eaf3b26ebb3f7a823b.png?fit=max\&auto=format\&n=TrrblT2KR7zYyGbN\&q=85\&s=bfdaa137bd82c72d769b9f9efa022156) 10. Add the role's ARN value in Metronome. \
    * Find the role's ARN value in AWS from the newly created role from [the roles page](https://console.aws.amazon.com/iam/home?#/roles/). The ARN uses the format `arn:aws:iam:::role/metronome-marketplace`. \* Back in Metronome, enter the role's ARN value in the `AWS ARN` field on step 2 of the menu.
11. Click **Save.** ## Provision AWS Marketplace customers in Metronome​ When a customer agrees to your Marketplace listing, you will need to provision their account in Metronome with a Metronome Contract that reflects the full details of the contract/subscription they signed with you in the Marketplace and AWS identified as the billing provider on that Contract. To connect a customer to AWS and have Metronome begin metering their invoices to AWS on your behalf: 1. Go to an existing customer's detail page in Metronome or create a new customer at **Customers** > **Add New Customer**. 2. Go to **Settings** > **Available Integrations** > **AWS** > **Get Started.** 3. Enter the **AWS customer ID** , **product code,** and **region**. * Unless you've specifically chosen a different AWS region, use `us-east-1`. If you specify the wrong region, you'll receive an error that the AWS customer cannot be found. * You can find the **product code** in the [AWS Marketplace Portal](https://aws.amazon.com/marketplace/management/products/saas) for the product you've set up. * The **AWS customer ID** is included in the token passed to the fulfillment URL associated with your Marketplace product. For details on decoding the token, refer to the [AWS documentation](https://docs.aws.amazon.com/marketplace/latest/userguide/saas-code-examples.html) and the section on [customer setup](https://docs.aws.amazon.com/marketplace/latest/userguide/saas-product-customer-setup.html). * The **Hourly usage-based pricing (per-unit)** checkbox must be selected if the product is configured as a "**Usage-based pricing** " product in the Marketplace. If this is a **contract with consumption** product, leave this checkbox unselected. 4. Create a new contract for the customer that matches the details of the contract they signed with you in the AWS Marketplace. Include any credits and commits the customer has as part of the contract. Learn how to [provision contracts](/guides/customers-billing/manage-customers/provision-a-customer) in Metronome. 5. Under the **Billing Configuration** section of the configure contract flow, select AWS as the billing provider. > [!WARNING] > > **CAUTION** > > You cannot add or change the billing provider after creating the contract. 6. Alternatively, you can use the following endpoints to set up AWS as a customer's billing provider and assign it to a contract * To set up a new customer configured with AWS Marketplace: * Call the [create customer](/api-reference/customers/create-a-customer) endpoint * In the request payload, include `customer_billing_provider_configurations`: * In the `configuration` property, specify `aws_product_code`, `aws_customer_id`, and `aws_region`. If the product is configured as a "**Usage-based pricing** " product in the Marketplace, also specify `aws_is_subscription_product` ```json theme={null} { // ... "customer_billing_provider_configurations": [ { "billing_provider": "aws_marketplace", "configuration": { "aws_customer_id": "", "aws_product_code": "", "aws_region": "", "aws_is_subscription_product": true // only if the product is configured as a usage-based pricing product }, "delivery_method": "direct_to_billing_provider" } ] } ``` * To configure an existing customer with AWS Marketplace: * Call the [set customer billing provider configurations](/api-reference/customers/set-billing-provider-configurations-for-a-customer) endpoint * In the request payload, include your configuration * In the `configuration` property, specify `aws_product_code`, `aws_customer_id`, and `aws_region`. If the product is configured as a "**Usage-based pricing** " product in the Marketplace, also specify `aws_is_subscription_product` ```json theme={null} { // ... { "billing_provider": "aws_marketplace", "customer_id": "", "configuration": { "aws_customer_id": "", "aws_product_code": "", "aws_region": "", "aws_is_subscription_product": true // only if the product is configured as a usage-based pricing product }, "delivery_method": "direct_to_billing_provider" } } ``` * To set up a new contract with invoices metered to AWS Marketplace: * Call the [create contract](/api-reference/contracts/create-a-contract) endpoint * In the request payload, include `billing_provider_configuration`: ```json theme={null} { // ... "billing_provider_configuration": { "billing_provider": "aws_marketplace", "delivery_method": "direct_to_billing_provider" } } ``` After you set AWS as that customer’s billing provider and begin sending usage events, Metronome starts metering that customer’s calculated invoice totals to AWS on your behalf. ## What Metronome meters to AWS​ When metering to AWS, Metronome sums up a customer’s total amount accrued across all contract invoices that have AWS set as the billing provider since the last metering request. Metronome sets the quantity for each metering record as the total dollar amount expressed in USD cents. If a customer purchased a commit or was offered a credit as part of their contract, Metronome meters like this: * **Prepaid commits** A contract in Metronome specifies a schedule over which the customer pays for their prepaid commit. Those inputs create one or more scheduled invoices. Metronome meters the amount the customer owes on the prepaid commit on the date associated with the service period of the scheduled invoice, not the created at date. * **Credits** As credits on a Metronome contract are not paid for, Metronome only meters overages reflected on invoice totals after the credit has been drawn down in its entirety. * **Postpaid commits** Metronome meters usage reflected on invoice totals throughout the duration of the contract. However, if the entirety of the postpaid commit isn’t consumed by the end of the contract, Metronome ignores the true-up invoice and doesn’t send it to the marketplace. This is because the true-up invoice isn’t finalized until after the Metronome grace period ends, at which point the metering endpoint for the marketplace has closed. This means you must handle the true-up in the marketplace directly. ## Handling marketplace customer lifecycle events in Metronome and your app​ Metronome stops metering if it detects subscription changes due to marketplace lifecycle events, and updates the customer's status in Metronome accordingly. However, you are responsible for ensuing that the customer's status is correctly represented in your application and ending the customer’s contract in Metronome, if relevant. To end the customer's contract in the [Metronome app](https://app.metronome.com/), go to the customer > click the contract > select the overflow menu > click **Edit Contract End Date.** To end the customer’s contract with the Metronome API, use the `/contracts/updateEndDate` endpoint. ## Limitations of AWS Marketplace listings​ Billing through the AWS Marketplace has some limitations. **AWS Marketplace only supports positive quantities through their [Metering Service](https://docs.aws.amazon.com/marketplace/latest/userguide/metering-service.html).** There's no way to *decrease* a customer's total bill. For example, consider a customer who was meant to receive \$1,000 in credits when they started using your product. Due to a typo, they erroneously received only \$100. The mistake gets noticed one week into their first billing period, when the customer notices a \$500 charge on their AWS bill. In Metronome, this mistake is easily rectified by adding an additional \$900 credit, but in AWS, there's no way to reduce that bill. If this situation arises, Metronome stops billing for that customer until their usage catches up to the amount they've already been billed. If this is insufficient to correct the problem, you must [issue a manual refund](https://docs.aws.amazon.com/marketplace/latest/userguide/refunds.html) through the AWS Marketplace. Contact your AWS representative or use the [Metronome support portal](https://app.metronome.com/support) for help. **AWS Marketplace strictly enforces the end of a customer's Marketplace contract or subscription.** The AWS Marketplace Metering Service only accepts requests for one hour after the customer's contract ends. Metronome typically applies late usage events to an invoice up to 24 hours after the billing period ends, but there’s no way to deliver that usage to AWS. Metronome sends one final request to AWS 15 minutes after the scheduled end of a customer's contract. Usage received after that cannot be billed through AWS. In the event of an outage, Metronome catches up when everything comes back online. If Metronome was unable to send usage to AWS for some period of time, the accrued usage is included in the next request to AWS. However, if the customer's contract has already ended and AWS's one hour grace period has elapsed, Metronome is unable to bill for the usage accrued during the down time. **Metronome's integration with AWS Marketplace only supports invoices with a USD fiat currency.** Metronome throws an error if you attempt to create a contract with AWS Marketplace set as the billing provider, and the rate card on the contract has a non-USD fiat currency. In the case where the contract is associated with other other invoices that are not in USD (for example, scheduled invoices associated with scheduled charges), only the USD invoices will be sent to AWS Marketplace. # Invoice with Azure Source: https://docs.metronome.com/integrations/marketplace-integrations/azure This guide describes how to enable Metronome to invoice on your behalf through the Azure Marketplace. ## Create an Azure Marketplace offer and plan​ Begin by creating an Azure Marketplace offer from your [Azure partner portal](https://partner.microsoft.com/dashboard/commercial-marketplace/private-offers). 1. Create a new **Software as a Service** offer from your partner portal and provide a name and alias. ![Azure create offer](https://mintcdn.com/metronome-b35a6a36/TrrblT2KR7zYyGbN/images/Integrations/azure/azure-create-offer-816919ead676043267cc30ba3e21a40e.png?fit=max\&auto=format\&n=TrrblT2KR7zYyGbN\&q=85\&s=b817e47e42e29f03f5a5e0a7d19b3926) 2. In the **Offer Setup** tab, select **Yes** for Selling through Microsoft and **No** for using Microsoft's license management service. ![Azure offer setup](https://mintcdn.com/metronome-b35a6a36/TrrblT2KR7zYyGbN/images/Integrations/azure/azure-offer-setup-09dde167c85dbae9aed4bec43006b2c5.png?fit=max\&auto=format\&n=TrrblT2KR7zYyGbN\&q=85\&s=1ba04128bb9e2d1d72b5abc6f2cdd836) 3. Click the **Technical configuration** tab to specify SaaS URL redirect for setup, Webhook URL, and a Microsoft Entra Application ID and Tenant ID. Retrieve these from the Azure portal. ![Technical configuration](https://mintcdn.com/metronome-b35a6a36/TrrblT2KR7zYyGbN/images/Integrations/azure/azure-tech-config-3f58cd74007e938d2ca53ab1cfa4809b.png?fit=max\&auto=format\&n=TrrblT2KR7zYyGbN\&q=85\&s=c2d97548deab83bf33d101bb78e81531) 4. Click the **Plan overview** tab to add plans for each rate card you defined in Metronome associated with this listing, and specify a plan ID and plan name. ![Create a new plan](https://mintcdn.com/metronome-b35a6a36/TrrblT2KR7zYyGbN/images/Integrations/azure/azure-create-plan1-efb3e2b38f58f35862393366e3f20da7.png?fit=max\&auto=format\&n=TrrblT2KR7zYyGbN\&q=85\&s=d3ca552bc1cab1e381c53c7b3c7a688a) ![Create a new plan](https://mintcdn.com/metronome-b35a6a36/TrrblT2KR7zYyGbN/images/Integrations/azure/azure-create-plan2-5ebd88c7f07d52ed59613668855068f2.png?fit=max\&auto=format\&n=TrrblT2KR7zYyGbN\&q=85\&s=94851791585693297b9dd56a007efda1) 5. Specify the pricing model in the **Pricing and Availability** tab. \
    \* Select the **Flat Rate** option with a monthly, yearly or multi-year Billing term with a \\$0 **Price per payment**. \* Add one metering service dimension with ONLY these values: \\
      * **ID** set to `usage_fee` \\* **Display name** set to Usage Fee \\* **Unit of measure** set to billing unit \\* **Price per unit** set to .01 \\* **Quantity included** set to 0
    \
> [!WARNING] > > **CAUTION** > > Deviating from these values will cause the integration to fail. ![Azure pricing](https://mintcdn.com/metronome-b35a6a36/TrrblT2KR7zYyGbN/images/Integrations/azure/azure-pricing-13ac177a2156d9e4e4ea677a1418da6d.png?fit=max\&auto=format\&n=TrrblT2KR7zYyGbN\&q=85\&s=40d31e5cfe7c86b4ebc935715b771e13) 6. Test your offer using the **Preview audience** tab ![Preview audience](https://mintcdn.com/metronome-b35a6a36/TrrblT2KR7zYyGbN/images/Integrations/azure/azure-preview-audience-3aa2fa8b417b5402a109000713301af1.png?fit=max\&auto=format\&n=TrrblT2KR7zYyGbN\&q=85\&s=abce60154a8b6ee4f79a9140f46f55dc) ## Set up authentication for Metronome to meter on your behalf​ To invoice through the Azure Marketplace, set up authentication credentials for Metronome using your **Tenant ID** , **Client ID** and **Client Secret**. To retrieve these credentials: 1. Go to your [Azure portal](https://portal.azure.com/) and select the **Microsoft Entra ID service** (formerly known as the Azure Active Directory). ![Microsfot Entra ID](https://mintcdn.com/metronome-b35a6a36/TrrblT2KR7zYyGbN/images/Integrations/azure/azure-entra-id-910f613cb7e20647471a4fa53288e618.png?fit=max\&auto=format\&n=TrrblT2KR7zYyGbN\&q=85\&s=e899751ef38077fa1678987a1974d6da) 2. From the Microsoft Entra ID overview, click **App registrations** in the sidebar to view applications that are authenticated to access the marketplace. ![App registrations](https://mintcdn.com/metronome-b35a6a36/TrrblT2KR7zYyGbN/images/Integrations/azure/azure-app-registrations-5149a71426d25b64f3d9f82f98b6ada6.png?fit=max\&auto=format\&n=TrrblT2KR7zYyGbN\&q=85\&s=a034e8276d9831a06fa2a8b2c81fbcf1) 3. Click the **All applications** tab and select the desired application based on the client ID (also known as the Application ID). This is the application you used to set up the marketplace listing. ![All Azure applications](https://mintcdn.com/metronome-b35a6a36/TrrblT2KR7zYyGbN/images/Integrations/azure/azure-app-registrations-list-973fcf7ed13d3fe37b67c64bea8848ed.png?fit=max\&auto=format\&n=TrrblT2KR7zYyGbN\&q=85\&s=5442b9cb5337bf3e5fa1c19231ba6c37) 4. Add application credentials to Metronome.
    * From the Application page, in the **Essentials** section, copy the **Tenant ID** and **Application ID**. * Click into the **Client credentials** to generate and copy a **Client secret**. ![Registration details](https://mintcdn.com/metronome-b35a6a36/TrrblT2KR7zYyGbN/images/Integrations/azure/azure-app-registration-detail-bffcfa978b730d18e24cd6b6f5646100.png?fit=max\&auto=format\&n=TrrblT2KR7zYyGbN\&q=85\&s=3bba8020f3bb772b01c1a009cdc64e10) * In Metronome, go to **General Settings** > Integrations > Available Integrations > Azure Marketplace card > **Get Started**. * Enter the **Tenant ID** , **Application ID** , and **Client secret** into their respective fields.
5. Click **Save.** ## Provision Azure Marketplace customers in Metronome​ When a customer agrees to your Azure Marketplace offer, you must to provision their account in Metronome with a Metronome contract that reflects the full details of the offer they signed with you in the marketplace, with Azure identified as the billing provider on that contract. Before provisioning the customer in Metronome, ensure the customer has completed the marketplace signup flow and has been provisioned in your SaaS system. Additionally, make sure the subscription is activated in Azure Marketplace via Azure's [activate subscription API](https://learn.microsoft.com/en-us/partner-center/marketplace/partner-center-portal/pc-saas-fulfillment-subscription-api#activate-a-subscription). When complete, you should have a unique Subscription ID for the customer’s accepted offer and the `saasSubscriptionStatus` as `Subscribed`. To connect a customer to Azure and have Metronome begin metering their invoices to Azure on your behalf: 1. Go to an existing customer's detail page in Metronome or create a new customer at **Customers** > **Add New Customer**. 2. Go to **Settings** > Available Integrations > Azure > **Get Started.** 3. Enter the **Azure subscription ID.** 4. Create a new contract for the customer that matches the details of the contract they signed with you in the marketplace. Include any credits and commits the customer has as part of the contract. 5. Under the **Billing Configuration** section of the configure contract flow, select Azure as the billing provider. > [!WARNING] > > **CAUTION** > > You cannot add or change the billing provider after creating the contract. 6. Alternatively, you can use the following endpoints to set up Azure as a customer's billing provider and assign it to a contract * To set up a new customer configured with Azure: * Call the [create customer](/api-reference/customers/create-a-customer) endpoint * In the request payload, include `customer_billing_provider_configurations`: * In the `configuration` property, specify `azure_subscription_id` ```json theme={null} { // ... "customer_billing_provider_configurations": [ { "billing_provider": "azure_marketplace", "configuration": { "azure_subscription_id": "" }, "delivery_method": "direct_to_billing_provider" } ] } ``` * To configure an existing customer with Azure: * Call the [set customer billing provider configurations](/api-reference/customers/set-billing-provider-configurations-for-a-customer) endpoint * In the request payload, include your configuration * In the `configuration` property, specify `azure_subscription_id` ```json theme={null} { // ... { "billing_provider": "azure_marketplace", "customer_id": "", "configuration": { "azure_subscription_id": "" }, "delivery_method": "direct_to_billing_provider" } } ``` * To set up a new contract with invoices metered to Azure: * Call the [create contract](/api-reference/contracts/create-a-contract) endpoint * In the request payload, include `billing_provider_configuration`: ```json theme={null} { // ... "billing_provider_configuration": { "billing_provider": "azure_marketplace", "delivery_method": "direct_to_billing_provider" } } ``` After you set Azure as that customer’s billing provider and begin sending usage events, Metronome starts metering that customer’s calculated invoice totals to Azure on your behalf. ## What Metronome meters to Azure​ When metering to AWS or Azure, Metronome sums up a customer’s total amount accrued across all contract invoices that have Azure set as the billing provider since the last metering request. Metronome sets the quantity for each metering record as the total dollar amount expressed in USD cents. If a customer purchased a commit or was offered a credit as part of their contract, Metronome meters like this: * **Prepaid commits** A contract in Metronome specifies a schedule over which the customer pays for their prepaid commit. Those inputs create one or more scheduled invoices. Metronome meters the amount the customer owes on the prepaid commit on the date associated with the service period of the scheduled invoice, not the created at date. * **Credits** As credits on a Metronome contract are not paid for, Metronome only meters overages reflected on invoice totals after the credit has been drawn down in its entirety. * **Postpaid commits** Metronome meters usage reflected on invoice totals throughout the duration of the contract. However, if the entirety of the postpaid commit isn’t consumed by the end of the contract, Metronome ignores the true-up invoice and doesn’t send it to the marketplace. This is because the true-up invoice isn’t finalized until after the Metronome grace period ends, at which point the metering endpoint for the marketplace has closed. This means you must handle the true-up in the marketplace directly. ## Handle marketplace customer lifecycle events in Metronome and your app​ Metronome stops metering if it detects subscription changes due to marketplace lifecycle events, and updates the customer's status in Metronome accordingly. However, you are responsible for ensuing that the customer's status is correctly represented in your application and ending the customer’s contract in Metronome, if relevant. To end the customer's contract in the [Metronome app](https://app.metronome.com/), go to the customer > click the contract > select the overflow menu > click **Edit Contract End Date**. To end the customer’s contract with the Metronome API, use the `/contracts/updateEndDate` endpoint. ## Limitations of Azure Marketplace offers​ Billing through the Azure Marketplace has some limitations. **Azure Marketplace only supports positive quantities through their metering service.** There's no way to *decrease* a customer's total bill. For example, consider a customer who was meant to receive \$1,000 in credits when they started using your product. Due to a typo, they erroneously received only \$100. The mistake gets noticed one week into their first billing period, when the customer notices a \$500 charge on their Azure bill. In Metronome, this mistake is easily rectified by adding an additional \$900 credit, but in Azure, there's no way to reduce that bill. If this situation arises, Metronome stops billing for that customer until their usage catches up to the amount they've already been billed. If this is insufficient to correct the problem, you must issue a manual refund through Azure support. Contact us via the [Metronome support portal](https://app.metronome.com/support) for help. **End of a customer's Marketplace contract supports a 1 hour grace period for events.** To ensure that the end of a customer’s subscription is handled promptly, Metronome provides a 1 hour grace period of events sent after the completion of the subscription. While Metronome normally supports a grace period of up to 24 hours after the billing period ends, the Azure integration currently is limited to 1 hour. This means usage received after that cannot be billed through Azure. Metronome automatically disables metering 2 hours after the subscription ends. In the event of an outage, Metronome catches up when everything comes back online. If Metronome was unable to send usage to Azure for some period of time, the accrued usage is included in the next request to Azure. However, if the customer's contract already ended and the grace period elapsed, Metronome is unable to bill for the usage accrued during the down time. **Metronome's integration with Azure Marketplace only supports invoices with a USD fiat currency.** Metronome throws an error if you attempt to create a contract with Azure Marketplace set as the billing provider, and the rate card on the contract has a non-USD fiat currency. In the case where the contract is associated with other other invoices that are not in USD (for example, scheduled invoices associated with scheduled charges), only the USD invoices will be sent to Azure Marketplace. # Invoice with GCP Source: https://docs.metronome.com/integrations/marketplace-integrations/gcp This guide describes how to enable Metronome to invoice on your behalf through GCP Marketplace. ## Set up GCP authentication for Metronome to meter on your behalf In order to meter your listings, Metronome will require access to the procurement and metering APIs in your marketplace GCP project. Metronome will access your project via [Workload Identity Federation](https://cloud.google.com/iam/docs/workload-identity-federation), which allows federated access to your project by Metronome without the need to store long-lived tokens or keys. You will then associate a [Google Service Account](https://cloud.google.com/iam/docs/service-account-overview) with the Workload Identity Federation pool, to which you will attach the appropriate fine-grained permissions for Metronome's metering operations. To assist with deploying these resources, Metronome provides a set of configuration files and scripts that will walk you through deploying through either Terraform, a Bash script, or a self-guided method using the `gcloud` CLI utility. Those suggested configurations are available in [Github](https://github.com/Metronome-Industries/metronome-gcp-marketplace-configuration). You will need some information from Metronome to fully configure this integration properly, and in return, Metronome will need some output from this process back. Here are the steps: 1. In Metronome, go to **Developer** > **Integrations** > **Available Integrations** > **GCP Marketplace** > click **Get started.** 2. Copy Metronome's **Service Account ID**, **AWS Account ID**, and **AWS Lambda Role Name** from the menu: ![GCP service account ID](https://mintcdn.com/metronome-b35a6a36/IMIJTftzi5_ibFC5/images/Integrations/gcp/gcp-service-account-id.png?fit=max\&auto=format\&n=IMIJTftzi5_ibFC5\&q=85\&s=bead45d6f3ad0ce9f6f3e94e40736a4c) 3. In GCP, go to the [GCP Console welcome page](https://console.cloud.google.com/welcome) and select your target project from the project picker in the top left. Your **Project ID** and **Project Number** will be displayed here: ![GCP project details](https://mintcdn.com/metronome-b35a6a36/IMIJTftzi5_ibFC5/images/Integrations/gcp/gcp-project-details.png?fit=max\&auto=format\&n=IMIJTftzi5_ibFC5\&q=85\&s=2a14b2f06bf2cdbe97ec62b1b89c3eb8) 4. Using any of the configuration methods provided in the [Github repository](https://github.com/Metronome-Industries/metronome-gcp-marketplace-configuration), supply your **metronome\_service\_account\_id**, **metronome\_aws\_account\_id**, **metronome\_aws\_lambda\_role\_name**, **project\_id**, and **project\_number** as input arguments. This will deploy a **Workload Identity Federation Pool**, an **AWS Workload Identity Federation Provider**, and a **Service Account** to your project with the appropriate configuration.
    * For Terraform configuration, supply the required variables to the module: ```bash theme={null} project_id = "my-gcp-project-id" project_number = "123456789012" metronome_service_account_id = "m-123456789012abcdef" metronome_aws_account_id = "123456789012" metronome_aws_lambda_role_name = "metronome-lambda-role" ``` * For the Bash or self-guided `gcloud` configuration, set the appropriate variables on your environment: ```bash theme={null} export GCP_PROJECT_ID="my-gcp-project-id" export GCP_PROJECT_NUMBER="123456789012" export METRONOME_SERVICE_ACCOUNT_ID="m-123456789012abcdef" export METRONOME_AWS_ACCOUNT_ID="123456789012" export METRONOME_AWS_LAMBDA_ROLE_NAME="metronome-lambda-role" ```
5. Also in GCP console, Metronome will need the appropriate GCP APIs enabled in order to authenticate to your project, discover your GCP entitlements, and report usage to GCP. See [GCP's Documentation](https://cloud.google.com/apis/docs/getting-started#enabling_apis) for more information on how to enable APIs, and ensure the following APIs are enabled: \
    * Identity and Access Management (IAM) API \* IAM Service Account Credentials API \* Cloud Commerce Partner Procurement API \* Service Control API \* Service Management API
6. Finally, go to the [Workload Identity Federation pools](https://console.cloud.google.com/iam-admin/workload-identity-pools) page in your GCP console and click on the Pool that was created in step 4. Click **Connected service accounts**, and then **Download** next to the service account we created in step 4. Save this credentials file for submission to Metronome in a later step. ![GCP workload identity download](https://mintcdn.com/metronome-b35a6a36/IMIJTftzi5_ibFC5/images/Integrations/gcp/gcp-workload-identity-download.png?fit=max\&auto=format\&n=IMIJTftzi5_ibFC5\&q=85\&s=383439e3f3191fab33f5a81c6d526480) ## Create a GCP Marketplace listing With federated access to your project configured, we now proceed to configuring your listing for usage-based billing through Metronome: 1. You must have access to the [GCP Producer Portal](https://cloud.google.com/marketplace/docs/partners/integrated-saas), which includes [registering with Google as a vendor](https://cloud.google.com/marketplace/docs/partners/get-started#requirements). 2. From the GCP Producer Portal home page, use **Add Product** to begin setting up a new listing. ![GCP add product](https://mintcdn.com/metronome-b35a6a36/IMIJTftzi5_ibFC5/images/Integrations/gcp/gcp-add-product.png?fit=max\&auto=format\&n=IMIJTftzi5_ibFC5\&q=85\&s=d28822560c799578e3e6dea79cc8982b) 3. Complete the **Product Details** section. This is all identifying information about your listing — Metronome does not require any specific settings here. ![Product details](https://mintcdn.com/metronome-b35a6a36/IMIJTftzi5_ibFC5/images/Integrations/gcp/gcp-product-details-page.png?fit=max\&auto=format\&n=IMIJTftzi5_ibFC5\&q=85\&s=88e88ae2082eca916bdf0ba977eea393) 4. Complete the **Pricing** section. In particular, in the **Price Model** tab, you will create a **plan** with a **usage-based metric** and **pricing** for that metric. Metronome has specific requirements for each: \
    \* Create a new **plan** and add a **metric** with the following settings: \\
      * **Metric ID** set to `usage_fee` \\* **Reporting unit** set to `count` \\* **Display unit** set to `Custom` \\* **Custom unit**: We recommend something generic like "**Usage Fee**". Do **not** set the Custom unit to a value that implies an actual currency, e.g. "**USD**".
    \> \\[!WARNING] \> \> **CAUTION** \> \> The metric ID must be called `usage_fee` for the integration to work correctly. ![GCP metric configuration](https://mintcdn.com/metronome-b35a6a36/IMIJTftzi5_ibFC5/images/Integrations/gcp/gcp-metric-configuration.png?fit=max\\&auto=format\\&n=IMIJTftzi5_ibFC5\\&q=85\\&s=9811cec57b9c51f9c09016393f8f8082) \* Once the metric is submitted, configure **pricing** on the metric by adding a **usage fee** with the following settings: \\
      * **Display quantity** set to `1` \\* **Price** set to `0.01`
    \> \\[!WARNING] \> \> **CAUTION** \> \> Deviating from these values will cause the integration to fail. ![GCP pricing configuration](https://mintcdn.com/metronome-b35a6a36/IMIJTftzi5_ibFC5/images/Integrations/gcp/gcp-pricing-configuration.png?fit=max\\&auto=format\\&n=IMIJTftzi5_ibFC5\\&q=85\\&s=199a6f03ff1331f0ef060f3c601c2171) \* You will then be asked to create **feature(s)** on your listing. Metronome is not opinionated on what your feature(s) are named, but you will need to have at least one feature with your usage-based pricing plan attached. ![GCP feature configuration](https://mintcdn.com/metronome-b35a6a36/IMIJTftzi5_ibFC5/images/Integrations/gcp/gcp-feature-configuration.png?fit=max\\&auto=format\\&n=IMIJTftzi5_ibFC5\\&q=85\\&s=3fbf97326e5bc40c70daf3659dcb469a) \* You will additionally fill out the **Tax Category** and **Terms & Policies** sections. There are no Metronome-specific requirements for these sections. \
5. Complete the final section, **Technical Integration**. Here, in particular, you will need to configure your Metronome-provided service account with access to the appropriate APIs in order for Metronome to have access to meter your listing. Completing this section will require your **Metronome Service Account ID** that you created and deployed in the [Set up Workload Identity Federation](#set-up-workload-identity-federation) section.
    * In the **Billing Integration** section, under step 1, you will need to provide Metronome's service account ID access to **Partner Procurement API.** Metronome requires this access in order to read and track metadata about your listing's entitlements. Click **Add Service Account** and type or paste in Metronome's service account ID: ![GCP procurement API access](https://mintcdn.com/metronome-b35a6a36/IMIJTftzi5_ibFC5/images/Integrations/gcp/gcp-procurement-api-access.png?fit=max\&auto=format\&n=IMIJTftzi5_ibFC5\&q=85\&s=ab7f38500c05b1b800383d27626b5c9c) * In the same **Partner Procurement API** integration step, just below the service account, your **Provider ID** will be displayed. Take note of this identifier as you will need to submit it to Metronome in the final step: ![GCP provider ID](https://mintcdn.com/metronome-b35a6a36/IMIJTftzi5_ibFC5/images/Integrations/gcp/gcp-provider-id.png?fit=max\&auto=format\&n=IMIJTftzi5_ibFC5\&q=85\&s=78b6ef5075747f26f4470df4b7ad4ab6) * The next step is to configure a **Pub/Sub integration**. Metronome does not require access to Pub/Sub at this time. However, here you may link your own internal service account(s) for any backend integrations you will use to manage GCP Marketplace subscriptions to your listing. ![GCP pub/sub integration](https://mintcdn.com/metronome-b35a6a36/IMIJTftzi5_ibFC5/images/Integrations/gcp/gcp-pub-sub-integration.png?fit=max\&auto=format\&n=IMIJTftzi5_ibFC5\&q=85\&s=b871c9363783afa8445fcd8f304c059a) * Finally, still in **Billing Integration**, under step 3, you will need to provide the same service account ID with access to the **Service Controller API** by again clicking **Add Service Account** and entering the identifier. Doing so permits Metronome to submit usage metrics to Google for billing: ![GCP service controller API access](https://mintcdn.com/metronome-b35a6a36/IMIJTftzi5_ibFC5/images/Integrations/gcp/gcp-service-controller-api-access.png?fit=max\&auto=format\&n=IMIJTftzi5_ibFC5\&q=85\&s=6b9ebf3f7e8399c09d7130ad673dc803) **Note**: Google may automatically attach a system service account here, which should remain in place. * Complete the **Frontend Integration** section and submit. There are no Metronome-specific requirements for this section.
6. With all required sections for your listing submitted, Google will proceed with a review and approval workflow before your listing may be published. ## Submit listing configuration to Metronome With **federated access configured** via a Workload Identity Pool, and with **Metronome's Service Account configured** with the appropriate permissions via your listing's Technical Integration, you are now ready to submit your configuration information to Metronome to finalize the integration: 1. In Metronome, return to **Developer** > **Integrations** > **Available Integrations** > **GCP Marketplace** > click **Get started.** 2. Submit your **Provider ID** and your **Workload Identity Configuration** JSON file to the appropriate fields: ![GCP configuration submission](https://mintcdn.com/metronome-b35a6a36/IMIJTftzi5_ibFC5/images/Integrations/gcp/gcp-configuration-submission.png?fit=max\&auto=format\&n=IMIJTftzi5_ibFC5\&q=85\&s=7a1d4d166cb85502a59e890c69c8c025) 3. Click **Save changes** to submit. Metronome will validate access has been granted to the listing correctly, and if successful, the integration will be saved. ## Provision GCP Marketplace customers in Metronome When a customer agrees to your Marketplace listing, you will need to provision their account in Metronome with a Metronome Contract that reflects the full details of the offer/subscription they signed with you in the Marketplace and GCP identified as the billing provider on that Contract. To connect a customer to GCP and have Metronome begin metering their invoices to GCP on your behalf: 1. Go to an existing customer's detail page in Metronome or create a new customer at **Customers** > **Add New Customer**. 2. Go to **Settings** > **Available Integrations** > **GCP** > **Get Started.** 3. Enter the **Entitlement ID** and **Service Name** for this customer's subscription: * You can find both pieces of information from the subscription or order in [GCP Producer Portal](https://console.cloud.google.com/producer-portal/). * **Entitlement ID** is the unique identifier representing your customer's offer/subscription in GCP. It is also referenced as **Order ID.** Example: ![GCP entitlement ID](https://mintcdn.com/metronome-b35a6a36/IMIJTftzi5_ibFC5/images/Integrations/gcp/gcp-entitlement-id.png?fit=max\&auto=format\&n=IMIJTftzi5_ibFC5\&q=85\&s=53be792a6eb7f9879b4189b76678e18d) * **Service Name** is a domain name that identifies your product/listing to Google. It is displayed as **Product** on an offer: ![GCP service name](https://mintcdn.com/metronome-b35a6a36/IMIJTftzi5_ibFC5/images/Integrations/gcp/gcp-service-name.png?fit=max\&auto=format\&n=IMIJTftzi5_ibFC5\&q=85\&s=a428fb308cbd8bf6855f1bde75ce1ba4) 4. Create a new contract for the customer that matches the details of the contract they signed with you in the GCP Marketplace. Include any credits and commits the customer has as part of the contract. Learn how to [provision contracts](/guides/customers-billing/manage-customers/provision-a-customer) in Metronome. 5. Under the **Billing Configuration** section of the configure contract flow, select GCP as the billing provider. > [!WARNING] > > **CAUTION** > > You cannot add or change the billing provider after creating the contract. 6. Alternatively, you can use the following endpoints to set up GCP as a customer's billing provider and assign it to a contract: * To set up a new customer configured with GCP Marketplace: * Call the [create customer](/api-reference/customers/create-a-customer) endpoint * In the request payload, include `customer_billing_provider_configurations`: * In the `configuration` property, specify `gcp_entitlement_id` and `gcp_service_name` ```json theme={null} { // ... "customer_billing_provider_configurations": [{ "billing_provider": "gcp", "delivery_method": "direct_to_billing_provider", "configuration": { "gcp_service_name": "", "gcp_entitlement_id": "" } }] } ``` * To configure an existing customer with GCP Marketplace: * Call the [set customer billing provider configurations](/api-reference/customers/set-billing-provider-configurations-for-a-customer) endpoint * In the request payload, include your configuration: * In the `configuration` property, specify `gcp_entitlement_id` and `gcp_service_name` ```json theme={null} { // ... { "billing_provider": "gcp", "delivery_method": "direct_to_billing_provider", "configuration": { "gcp_service_name": "", "gcp_entitlement_id": "" } } } ``` * To set up a new contract with invoices metered to GCP Marketplace: * Call the [create contract](/api-reference/contracts/create-a-contract) endpoint * In the request payload, include `billing_provider_configuration`: ```json theme={null} { // ... "billing_provider_configuration": { "billing_provider": "gcp", "delivery_method": "direct_to_billing_provider" } } ``` After you set GCP as that customer's billing provider and begin sending usage events, Metronome starts metering that customer's calculated invoice totals to GCP on your behalf. ## What Metronome meters to GCP When metering to GCP, Metronome sums up a customer's total amount accrued across all contract invoices that have GCP set as the billing provider since the last metering request. Metronome sets the quantity for each metering record as the total dollar amount expressed in USD cents. If a customer purchased a commit or was offered a credit as part of their contract, Metronome meters like this: * **Prepaid commits** A contract in Metronome specifies a schedule over which the customer pays for their prepaid commit. Those inputs create one or more scheduled invoices. Metronome meters the amount the customer owes on the prepaid commit on the date associated with the service period of the scheduled invoice, not the created at date. * **Credits** As credits on a Metronome contract are not paid for, Metronome only meters overages reflected on invoice totals after the credit has been drawn down in its entirety. * **Postpaid commits** Metronome meters usage reflected on invoice totals throughout the duration of the contract. However, if the entirety of the postpaid commit isn't consumed by the end of the contract, Metronome ignores the true-up invoice and doesn't send it to the marketplace. This is because the true-up invoice isn't finalized until after the Metronome grace period ends, at which point the metering endpoint for the marketplace has closed. This means you must handle the true-up in the marketplace directly. ## Handling marketplace customer lifecycle events in Metronome and your app Metronome stops metering if it detects subscription changes due to marketplace lifecycle events, and updates the customer's status in Metronome accordingly. However, you are responsible for ensuing that the customer's status is correctly represented in your application and ending the customer's contract in Metronome, if relevant. To end the customer's contract in the [Metronome app](https://app.metronome.com/), go to the customer > click the contract > select the overflow menu > click **Edit Contract End Date.** To end the customer's contract with the Metronome API, use the `/contracts/updateEndDate` endpoint. ## Limitations of GCP Marketplace listings Billing through the GCP Marketplace has some limitations. **GCP Marketplace only supports positive quantities through their usage reporting service.** There's no way to *decrease* a customer's total bill. For example, consider a customer who was meant to receive \$1,000 in credits when they started using your product. Due to a typo, they erroneously received only \$100. The mistake gets noticed one week into their first billing period, when the customer notices a \$500 charge on their GCP bill. In Metronome, this mistake is easily rectified by adding an additional \$900 credit, but in GCP, there's no way to reduce that bill. If this situation arises, Metronome stops billing for that customer until their usage catches up to the amount they've already been billed. If this is insufficient to correct the problem, you must issue a manual refund through the GCP Marketplace. Contact your GCP representative or use the [Metronome support portal](https://app.metronome.com/support) for help. **GCP Marketplace strictly enforces the end of a customer's Marketplace contract or subscription.** Metronome provides a 1 hour grace period of events sent after the completion of the subscription. While Metronome normally supports a grace period of up to 24 hours after the billing period ends, the GCP integration currently is limited to 1 hour. This means usage received after that cannot be billed through GCP. Metronome automatically disables metering 2 hours after the subscription ends. In the event of an outage, Metronome catches up when everything comes back online. If Metronome was unable to send usage to GCP for some period of time, the accrued usage is included in the next request to GCP. However, if the customer's contract has already ended and GCP's grace period has elapsed, Metronome is unable to bill for the usage accrued during the down time. **Metronome's integration with GCP Marketplace only supports invoices with a USD fiat currency.** Metronome throws an error if you attempt to create a contract with GCP Marketplace set as the billing provider, and the rate card on the contract has a non-USD fiat currency. In the case where the contract is associated with other invoices that are not in USD (for example, scheduled invoices associated with scheduled charges), only the USD invoices will be sent to GCP Marketplace. # Send usage events from Segment Source: https://docs.metronome.com/integrations/platform-integrations/segment Set up and ingest events into Metronome with [Segment](https://segment.com/). ## Initial setup​ 1. From the **Segment Destinations** page, click **Add Destination**. Search for and select **Metronome (Actions)** within the **Destinations Catalog**. 2. Click on **Configure Metronome (Actions)** , select the source you'd like to connect to, and give the destination a name (for example, *Metronome Instance #1*). 3. Enter your Metronome API token on the **Settings** pane in the **API Token** box and save the changes. ![Metronome destination setup](https://mintcdn.com/metronome-b35a6a36/TrrblT2KR7zYyGbN/images/Integrations/send-usage-events/metronome-destination-setup-a32dc2448ae9561bd7ddcdf4a948ceb1.gif?s=25d49fe3e685cfe59cd0d1d5c2121ff9) ## Data field mapping​ Map your Segment events to the Metronome usage event format. The five fields listed are the required fields for Metronome. To start, click the **Mappings** tab at the top of the **Settings** pane. You have a set of mappings by default. To add to or change them, choose **Edit Mapping** from the ellipsis dropdown. > [!WARNING] > > **ALL MAPPINGS ARE REQUIRED** > > You must specify a mapping even if the property name doesn't differ between the Segment event and the Metronome payload. The required fields for Metronome are: * `transaction_id` (string) - unique identifier for each event * `customer_id` (string) - which customer in Metronome the event applies to * `timestamp` (string) - when the event happened, in [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format * `event_type` (string) - the kind of event, for example `page_view` or `cpu_used` * `properties` (object) - key/value pairs with details of the event ![Mappings](https://mintcdn.com/metronome-b35a6a36/TrrblT2KR7zYyGbN/images/Integrations/send-usage-events/mappings-2ede9a0af564cae465d96971ca3592d0.png?fit=max\&auto=format\&n=TrrblT2KR7zYyGbN\&q=85\&s=f3c6b2d403b0a5bb673566813cb1e213) If your `track` call looks like: ```javascript theme={null} analytics.track('billing_event', { cid: '533c3db43f22', data: { action: 'runJob', jobId: 'fd82-aa0f-45a7-a756', username: 'jsmith' }, t: 'user_action', ts: new Date('2020-04-02T00:10:25.000Z') }); ``` then your field mapping should be: ![Segment mappings](https://mintcdn.com/metronome-b35a6a36/TrrblT2KR7zYyGbN/images/Integrations/send-usage-events/segment-mappings-0b122eb0ffc9cf8db09a4e93a3727840.png?fit=max\&auto=format\&n=TrrblT2KR7zYyGbN\&q=85\&s=0f56f517c9ed497bea79058b24ca65f1) > [!NOTE] > > **TRANSACTION ID REQUIRED** > > Metronome usage events require the `transaction_id` field to ensure all events are processed exactly once. The default mapping uses the [Segment `messageId` field](https://segment.com/docs/guides/duplicate-data/) as the Metronome `transaction_id`. This is probably ideal for most users, but if you want to control the Metronome `transaction_id` manually, you can provide a mapping to any field in the Segment event. ## Additional Destination Actions​ The integration supports [Destination Actions](https://segment.com/docs/connections/destinations/#destination-actions), allowing users to create *subscriptions*. This means that the Metronome (Actions) destination sends data to Metronome based on a set of conditions known as *triggers*. Create additional triggers and mappings by clicking on the **New Mapping** button on the **Mapping** pane. You can set a trigger for any number of conditions. For example, create a condition to trigger events to Metronome only when the `User ID` field is not an email address from your company (does not contain `@company.com`). ![New trigger](https://mintcdn.com/metronome-b35a6a36/TrrblT2KR7zYyGbN/images/Integrations/send-usage-events/new-trigger-dfdc25e1877ddd8222229a049aa2bba3.png?fit=max\&auto=format\&n=TrrblT2KR7zYyGbN\&q=85\&s=e2cf3c5580043cb13c1892604cc9ed29) # Sync into Salesforce Source: https://docs.metronome.com/integrations/platform-integrations/sfdc-integration To help power your sales-driven workflows, Metronome offers a native integration that syncs Metronome data back to your Salesforce instance daily. As sales and revenue operations teams are deeply embedded within Salesforce, it’s critical that Metronome data about how much spend a customer has committed to, how much of the products they’ve purchased access to are being used, and how much of their commitments have been burned down as a result makes its way back into Salesforce. Signals from this data can then be used to help these teams initiate upsells, cross sells, and downgrade motions in a timely fashion. The Salesforce integration can empower your customer-facing teams to quickly answer questions like: * What are the terms of my customer's current contract(s)? * What are their outstanding credits and commits? * How much of those credits and commits have been used up to date? * How has that consumption trended through the lifetime of the contract? * What is my customer's usage in the current month? What is their current month's spend (invoice total)? * How has that usage and spend trended through the lifetime of the contract? ## How the Salesforce integration works​ The Metronome → Salesforce integration is powered by a tool called Census. Census acts as an ETL service to push data from Metronome to your Salesforce instance daily. Setting up the integration in Metronome takes four steps: 1. Install the Metronome ↔ Salesforce package. 2. Set up your Census workspace. 3. Link Census to your Salesforce destination. 4. Determine what data to sync. You need to repeat this process in every Metronome environment (like Staging and Production) where you want data synced back to Salesforce. ## Set up the integration​ To set up the Salesforce integration: 1. In the [Metronome app](https://app.metronome.com/), click **Developer** in the left sidebar. 2. Click **Get Started** on the Salesforce card found under **Available Integrations**. 3. On Step 1 of the menu, click **Install Now** to download the Metronome ↔ Salesforce package. > [!WARNING] > > **CAUTION** > > Make sure that you install the package in the Salesforce instance that you intend to authenticate with in step 7. > > Clicking this link inside any non-production Metronome environment takes you to [test.salesforce.com](http://test.salesforce.com), whereas clicking this link inside the Metronome production environment takes you to [login.salesforce.com](http://login.salesforce.com). You can update the URL to ensure that you install the package in the desired Salesforce instance. * The page prompts you to select which Salesforce users you want to install this package for: Admins Only, All Users, or Specific Profiles. Give access to the user who will grant Census access to Salesforce in step 7. * After confirming your selection, click **Install**. The installation process may take a few seconds. 4. Once the Metronome ↔ Salesforce package successfully installs, return to Metronome. 5. On step 2 of the Salesforce card menu, click **Activate Now** to set up a Census workspace. 6. On step 3 of the menu, click **Link Salesforce** to grant Census access to Salesforce. Clicking this link takes you to Census. * Select which Salesforce domains you'd like to sync data to (Production or Sandbox). * Grant Census access to proceed by clicking **Allow**. This process may take a few seconds to complete. * Click **Finish** to return to Metronome and complete the integration set-up. 7. On step 4 of the Salesforce card menu, choose whether you want data synced for all customers in Metronome or just those linked to a Salesforce account. > [!TIP] > > **TIP** > > To link a Metronome customer to a Salesforce account, navigate to that customer’s page in Metronome, click **Settings,** find the Salesforce card under Linked Accounts, click **Connect** , and enter the Salesforce account ID you’d like to associate to that customer. You can also do this programmatically when creating customers in Metronome. 8. Click **Complete Setup** to complete the integration setup. Metronome then begins setting up your Census workspace and associated syncs. This process may take a few minutes. Once the setup process completes, the menu closes automatically and Salesforce appears listed under the **Active Integrations** section. The first set of data syncs kick off automatically. The syncs may take a couple of hours to complete and are scheduled to happen once a day. At this time, syncs cannot be configured to happen more frequently. ## Monitor the integration​ Once Census begins syncing data to your Salesforce instance, you can monitor the status of your daily syncs. To monitor the integration: 1. Go to **Developer** on the left sidebar and open the **Integrations** tab. 2. Click on the **Salesforce** row under the **Active Integrations** section. There are two tabs: one for **Completed** syncs and one for **Incomplete** (in progress) syncs. The **Completed** syncs tab shows by object type how many rows were attempted to be synced last and, of those rows, how many were successful versus how many failed. > [!NOTE] > > **INFO** > > The total row count reflects the number of rows that *changed* and therefore needed to be re-synced since the time of the last sync. It doesn’t reflect the total count of that record type. For example, if you have 1,000 customers listed in Metronome, but only three changed since the last sync, you should only see three total in the row listed under `metronome_Customer_c`. To troubleshoot any row sync failures, download a CSV file of the row sync errors. To do this, click the download button next to where the errors appear in the **Status** column. This file gives you a sampling of up to 100 failures from that sync for that object type to help you troubleshoot the issue. ## Available data types​ After setting up the integration, these data objects get synced from Metronome to your Salesforce instance on a daily basis. **metronome\_\_Credit\_Type\_\_c** | Columns | **Type** | **Description** | | - | - | - | | `Credit_Type_ID__c` | text | The unique identifier associated with the credit type (currency) | | `Name__c` | text | The name of the credit type | | `Environment_Type__c` | picklist | The name of the Metronome environment where this object lives | **metronome\_\_Customer\_\_c** | Columns | Type | **Description** | | - | - | - | | `Customer_ID__c` | text | The unique identifier associated with the customer | | `Name__c` | text | The name of the customer | | `Account__c` | lookup | References the associated Salesforce account for this customer if one has added to the customer in Metronome | | `Environment_Type__c` | picklist | The name of the Metronome environment where this object lives | **metronome\_\_Customer\_Ingest\_Alias\_\_c** | **Columns** | Type | **Description** | | - | - | - | | `Customer_Ingest_Alias_ID__c` | text | The unique identifier associated with the ingest alias | | `Customer__c` | lookup | References the associated customer for this ingest alias | | `Ingest_Alias__c` | text | The ingest alias associated with the customer | | `Environment_Type__c` | picklist | The name of the Metronome environment where this object lives | **metronome\_\_Rate\_Card\_\_c** | **Columns** | **Type** | **Description** | | - | - | - | | `Rate_Card_ID__c` | text | The unique identifier associated with the rate card | | `Name__c` | text | The name of the rate card | | `Description__c` | text area long | The description of the rate card | | `Environment_Type__c` | picklist | The name of the Metronome environment where this object lives | **metronome\_\_Contract\_\_c** | **Columns** | **Type** | **Description** | | - | - | - | | `Contract_ID__c` | text | The unique identifier associated with the contract | | `Customer__c` | lookup | References the associated customer for this contract | | `Rate_Card__c` | lookup | References the associated rate card for this contract | | `Name__c` | text | The name of the contract | | `Starting_On__c` | datetime | The inclusive starting time of the contract (UTC) | | `Ending_Before__c` | datetime or NULL | The exclusive ending time of the contract (UTC) | | `Usage_Statement_Schedule_Frequency__c` | pick list | The frequency with which usage statements are sent to the customer | | `Environment_Type__c` | picklist | The name of the Metronome environment where this object lives | **metronome\_\_Commit\_\_c** | **Columns** | **Type** | **Description** | | - | - | - | | `Commit_ID__c` | text | The unique identifier associated with the commit or credit | | `Customer__c` | lookup | References the associated customer for this commit or credit | | `Contract__c` | lookup | References the associated contract for this commit or credit | | `Name__c` | text or NULL | The name of the commit or credit | | `Type__c` | PickList | The type of commit or credit (one of prepaid, postpaid, or credit) | | `Priority__c` | number | The priority assigned to the commit or credit | | `Description__c` | text area long or NULL | The description of the commit or credit | | `Starting_On__c` | datetime | The inclusive starting time of the commit or credit (UTC) | | `Ending_Before__c` | datetime | The exclusive ending time of the commit or credit (UTC) | | `Total_Amount__c` | number | The total dollar amount of the commit or credit. If the commit or credit is broken out over multiple access segments, this represents the sum across all access segments | | `Current_Balance__c` | number | The current balance on the commit or credit as determined subtracting any burn down, including the current draft invoice, from the total amount | | `Total_Cost__c` | number | The total cost of the commit or credit. If the commit or credit is broken out over multiple invoice segments, this represents the sum across all invoice segments | | `Cost_Basis__c` | formula | The total cost / the total amount of the commit or credit | | `Environment_Type__c` | picklist | The name of the Metronome environment where this object lives | **metronome\_\_Invoice\_\_c** This includes draft and finalized invoices. | **Columns** | **Type** | **Description** | | - | - | - | | `Invoice_ID__c` | text | The unique identifier associated with the invoice | | `Contract__c` | lookup | References the associated contract for this invoice | | `Customer__c` | lookup | References the associated customer for this invoice | | `Credit_Type__c` | lookup | References the associated credit type for this invoice | | `Type__c` | pick list | The invoice type (Scheduled, Usage, Refund, True-up, Adhoc) | | `Starting_On__c` | datetime | The inclusive starting time of the period this invoice covers (UTC) | | `Ending_Before__c` | datetime | The exclusive ending time of the period this invoice covers (UTC) | | `Total__c` | number | The invoice total | | `Status__c` | picklist | The Metronome invoice status (One of Draft, Finalized, Void) | | `Issued_At__c` | datetime | The time at which the invoice was issued (UTC) | | `Environment_Type__c` | picklist | The name of the Metronome environment where this object lives | **metronome\_\_Invoice\_Line\_Item\_\_c** This includes draft and finalized invoices. | **Columns** | **Type** | **Description** | | - | - | - | | `Invoice_Line_Item_ID__c` | text | The unique identifier associated with the invoice line item | | `Invoice__c` | lookup | References the associated invoice for this line item | | `Credit_Type__c` | lookup | References the associated credit type for this line item | | `Commit__c` | lookup | References the associated commit for this line item | | `Name__c` | text | The line item description | | `Quantity__c` | number | The quantity associated with the line item | | `Unit_Price__c` | number | The unit price with the line item | | `Product_Type__c` | text | The product ID associated with the line item | | `Total__c` | number | The line item total | | `Starting_On__c` | datetime | The inclusive starting time of when the line item is effective from (UTC) | | `Ending_Before__c` | datetime | The exclusive ending time of when the line item is effective from (UTC) | | `Environment_Type__c` | picklist | The name of the Metronome environment where this object lives | **metronome\_\_InvoiceLineItemPricingDimensionAssoc\_\_c** | Columns | Type | **Description** | | - | - | - | | `External_Association_ID__c` | text | The unique identifier for the many to many mapping between invoice line item and pricing dimension | | `Invoice_Line_Item__c` | lookup | References the associated line item for the many to many mapping | | `Pricing_Dimension__c` | lookup | References the associated pricing dimension for the many to many mapping | | `Environment_Type__c` | picklist | The name of the Metronome environment where this object lives | **metronome\_\_Pricing\_Dimension\_\_c** | Columns | Type | **Description** | | - | - | - | | `Pricing_Dimension_ID__c` | text | The unique identifier associated with the pricing dimension set on the invoice line item | | `Name__c` | text | The key of the pricing dimension set on the invoice line item | | `Value__c` | text | The value of the pricing dimension set on the invoice line item | | `Environment_Type__c` | picklist | The name of the Metronome environment where this object lives | **metronome\_\_InvoiceLineItemInvoicingGroupAssoc\_\_c** | Columns | Type | **Description** | | - | - | - | | `External_Association_ID__c` | text | The unique identifier for the many to many mapping between invoice line item and invoicing group | | `Invoice_Line_Item__c` | lookup | References the associated line item for the many to many mapping | | `Invoicing_Group__c` | lookup | References the associated invoicing group for the many to many mapping | | `Environment_Type__c` | picklist | The name of the Metronome environment where this object lives | **metronome\_\_Invoicing\_Group\_\_c** | Columns | Type | **Description** | | - | - | - | | `Invoicing_Group_ID__c` | text | The unique identifier associated with the presentation (invoicing) group key set on the invoice line item | | `Name__c` | text | The key of the presentation (invoicing) group key set on the invoice line item | | `Value__c` | text | The value of the presentation (invoicing) group key set on the invoice line item | | `Environment_Type__c` | picklist | The name of the Metronome environment where this object lives | # Set up the Metronome Workato connector Source: https://docs.metronome.com/integrations/platform-integrations/workato-connector Our clients commonly use the IPAAS system Workato to build integrations with Metronome. These integrations enable a variety of workflows, such as * Invoicing through third-party billing systems * Customer provisioning * Contract provisioning To enable these integration patterns, Metronome has invested in building a Workato connector. This connector acts like an SDK, enabling users in Workato to perform actions on Metronome endpoints. To set up a connection to your Metronome environment: 1. Install the [Workato connector](https://app.workato.com/custom_adapters/543474?token=f676fd9c66ce244573d8a8167942493b6696ef7660b1b9bbbec98cb2dd8e9963). 2. Generate an API token in Metronome. See [API authorization](/api-reference/authorization) for instructions. 3. Create a new connection in Workato and paste the API token in the appropriate field. 4. This connection is available to use in new workflows! > [!NOTE] > > **METRONOME ENVIRONMENTS** > > Please note that a unique connection needs to be made for each Metronome environment you wish to connect. # Anrok Source: https://docs.metronome.com/integrations/tax-integrations/anrok Learn how to configure Anrok as your tax provider with Metronome and Stripe invoicing. [Anrok](https://www.anrok.com/) is a tax compliance platform. Metronome integrates with Anrok through Stripe—Anrok operates as a Stripe Tax provider through the [Anrok Stripe app](https://marketplace.stripe.com/apps/anrok). The key difference is that Anrok handles the tax calculation and compliance rather than Stripe's native engine. ## Prerequisites 1. Install the [**Anrok app**](https://marketplace.stripe.com/apps/anrok) in your Stripe dashboard from the Stripe App Marketplace. 2. **Configure Anrok** to connect to your Stripe account. Follow Anrok's setup instructions at [anrok.com/integrations/stripe](https://anrok.com/integrations/stripe). In the Stripe Dashboard, go to **Settings > Tax > [Integrations](https://dashboard.stripe.com/settings/tax/integrations)** and confirm Anrok is selected as your tax calculation provider and that "Use automatic tax" is toggled **ON**. See [Stripe's third-party tax apps guide](https://docs.stripe.com/tax/third-party-apps) for details. 1. [Complete tax registration](https://docs.stripe.com/tax/registering) in the applicable jurisdictions for sales tax, VAT, and GST. 3. [Connect your Stripe account](/integrations/invoice-integrations/stripe) to Metronome. 4. Link each Metronome customer to their Stripe customer ID. 5. Ensure each Stripe customer has a [**Customer Address**](https://docs.stripe.com/api/customers/object#customer_object-address) set and is marked as **Taxable**. 6. Once you've completed setup, contact us via the [Metronome support portal](https://app.metronome.com/support) to enable tax application on your account. > [!NOTE] > > The Customer Address field is the `address` object on the [Stripe Customer object](https://docs.stripe.com/api/customers/object#customer_object-address), which determines tax jurisdiction. Failure to assign a Customer Address results in failure to apply tax. ## Step 1: Create Stripe products Anrok uses the Stripe product on each invoice line item to determine tax treatment. Create Stripe products and assign appropriate [tax codes](https://docs.stripe.com/tax/tax-codes). If a Stripe product doesn't have a tax code assigned, Anrok falls back to a default product classification. However, it's recommended to explicitly assign tax codes for accuracy. ## Step 2: Create the Stripe Product ID custom field in Metronome 1. Create a `stripe_product_id` [custom field](/api-reference/custom-fields) on the **Product** entity in Metronome. 2. For each Metronome product, set the `stripe_product_id` value to the corresponding Stripe product ID. See [Stripe Tax Step 2](/integrations/tax-integrations/stripe-tax#step-2-create-the-stripe-product-id-custom-field-in-metronome) for detailed instructions. ## Step 3: Configure entity mapping Configure the entity mapping in Metronome to pass the product ID to Stripe: 1. Go to **Developer > Integrations > Stripe > Edit Mapping**. 2. Add the following mapping: | Stripe vendor entity | Stripe vendor key | Metronome entity | Metronome key | | - | - | - | - | | `invoiceitem.price` | `product` | `ContractProduct` | `stripe_product_id` | 3. Click **Save**. ## Step 4: Configure invoice settings **For arrears invoices (end-of-period usage invoices):** Anrok calculates tax inline through the Stripe app. You don't need "Leave invoices as drafts" enabled for this flow. **For threshold billing ([prepaid balance recharges](/guides/customers-billing/optimize-customer-experience/prepaid-balance-thresholds), spend thresholds):** Set `tax_type: "STRIPE"` and `payment_type: "INVOICE"` in the `payment_gate_config`. See the [Stripe Tax threshold billing docs](/integrations/tax-integrations/stripe-tax#threshold-billing) for the exact API payload. ## Test your configuration 1. Use your **Metronome sandbox** (connected to **Stripe test mode**) to test. 2. Create a customer with a valid Stripe customer ID and [Customer Address](https://docs.stripe.com/api/customers/object#customer_object-address). 3. Generate an invoice and verify in Stripe that Anrok has applied tax. 4. Confirm the tax line items appear on the finalized Stripe invoice. ## FAQ and troubleshooting **Q: My invoices are failing or are finalizing without tax -- what should I check?** The most common causes are a missing [Customer Address](https://docs.stripe.com/api/customers/object#customer_object-address) on the Stripe customer or an incomplete entity mapping in Metronome. Start by confirming that the Stripe customer has sufficient location information to accurately calculate tax rates for the customer. Next, check if the entity mapping is complete in Metronome. If both are verified and tax still isn't being applied, contact us via the [Metronome support portal](https://app.metronome.com/support) to check your account configuration. **Q: Can I use Anrok for compliance and Stripe Tax for calculation?** Yes. Many customers use Stripe Tax for the actual tax calculation and Anrok for tax compliance, filing, and reporting. In this case, follow the [Stripe Tax setup guide](/integrations/tax-integrations/stripe-tax)—Anrok automatically picks up the transaction data from Stripe for compliance purposes. **Q: How do I verify Anrok is working?** After generating and finalizing an invoice, check the Stripe invoice object. You should see: ```json theme={null} { "automatic_tax": { "enabled": true, "provider": "anrok", "disabled_reason": null, "liability": { "type": "self" }, "status": "complete" } } ``` If you see `"enabled": false` or `"provider": null`, the integration isn't active. Verify the [Anrok app is installed](https://marketplace.stripe.com/apps/anrok) in Stripe. Otherwise, contact us via the [Metronome support portal](https://app.metronome.com/support) for tax automation. **Q: Do I need to set a default tax behavior in Stripe?** In the Stripe dashboard, make sure that you have a default tax behavior selected to ensure tax is correctly added to each invoice. # Avalara Source: https://docs.metronome.com/integrations/tax-integrations/avalara Learn how to configure Avalara AvaTax as your tax provider with Metronome and Stripe invoicing. If you use **Stripe** as your invoice provider, Avalara integrates through Stripe rather than directly with Metronome through the [Avalara AvaTax app](https://marketplace.stripe.com/apps/avalara-avatax) from the Stripe App Marketplace. This uses Stripe's [third-party tax app framework](https://docs.stripe.com/tax/third-party-apps) for inline tax calculation. ## Prerequisites 1. Install the [**Avalara AvaTax app**](https://marketplace.stripe.com/apps/avalara-avatax) in your Stripe dashboard. Connect your Avalara account to Stripe and verify the connection in both dashboards. See [Avalara's Stripe integration page](https://www.avalara.com/us/en/products/integrations/stripe-invoicing.html) for Avalara-side configuration. 2. In the Stripe Dashboard, go to [**Settings > Tax > Integrations**](https://dashboard.stripe.com/settings/tax/integrations) and confirm Avalara is selected as your tax calculation provider and that "Use automatic tax" is toggled **ON**. 1. [Complete tax registration](https://docs.stripe.com/tax/registering) in the applicable jurisdictions for sales tax, VAT, and GST. 3. [Connect your Stripe account](/integrations/invoice-integrations/stripe) to Metronome. 4. Link each Metronome customer to their Stripe customer ID. 5. Ensure each Stripe customer has a [**Customer Address**](https://docs.stripe.com/api/customers/object#customer_object-address) set and is marked as **Taxable**. > [!NOTE] > > The Customer Address field is the `address` object on the [Stripe Customer object](https://docs.stripe.com/api/customers/object#customer_object-address), which determines tax jurisdiction. Failure to assign a Customer Address results in failure to apply tax. ## Step 1: Create TaxCode custom field To pass tax metadata from Metronome to Stripe: 1. Create a [custom field](/api-reference/custom-fields) on the **Product** entity in Metronome named `TaxCode` (exact casing is required by [Avalara's metadata specification](https://knowledge.avalara.com/bundle/ymp1659710033243_ymp1659710033243/page/Invoice_line_item_metadata.html)). 2. For each product, set the `TaxCode` value to the corresponding Avalara tax code. Browse available codes at the [Avalara tax code catalog](https://taxcode.avatax.avalara.com/). ## Step 2: Create entity mappings 1. Go to **Developer > Integrations > Stripe > Edit Mapping**. 2. Add the following mapping: | Stripe vendor entity | Stripe vendor key | Metronome entity | Metronome key | | - | - | - | - | | `invoiceitem.metadata` | `TaxCode` | `ContractProduct` | `TaxCode` | > [!NOTE] > > If a line item does not have a specified tax code, the standard state sales tax will apply for the customer's jurisdiction. Explicitly setting tax codes ensures accurate classification. 3. Click **Save**. ## Step 3: Configure invoice settings Set **"Leave invoices as drafts"** to **ON** in your Stripe integration settings (under **Developer > Integrations > Stripe > Settings**). > [!NOTE] > > Avalara requires invoices to remain in draft so it can calculate and apply tax before finalization. ## Test your configuration 1. Use your **Metronome sandbox** (connected to your **Stripe Sandbox**) to test. 2. Create a customer with a valid Stripe customer ID and [Customer Address](https://docs.stripe.com/api/customers/object#customer_object-address). 3. Generate an invoice in Metronome and view the draft invoice in Stripe. 4. Confirm the tax line items appear on the finalized Stripe invoice after Avalara processes it. ## FAQ and troubleshooting **Q: My invoices are failing or are finalizing without tax -- what should I check?** Start by confirming that the Stripe customer has sufficient location information to accurately calculate tax rates for the customer. Ensure both the [Customer Address](https://docs.stripe.com/api/customers/object#customer_object-address) and tax location are set. Then verify that the "Leave invoices as drafts" setting is **ON** in your Stripe integration settings, and that your entity mapping is configured with `TaxCode` values on your Metronome products. If everything looks correct, contact us via the [Metronome support portal](https://app.metronome.com/support) to verify your tax setup. **Q: Tax is being calculated, but the rate seems wrong or is showing as 0%.** Avalara determines tax rates based on the customer's address and the tax code assigned to the line item. Some products—like SaaS in certain states—may be tax-exempt, which results in a 0% rate. Verify the tax code you've assigned by checking the [Avalara tax code catalog](https://taxcode.avatax.avalara.com/). If the rate still seems incorrect, contact Avalara support directly, as tax rate accuracy is managed on their side. **Q: What happens if I don't assign a `TaxCode` to a product?** If a line item doesn't have a `TaxCode` set in its metadata, Avalara applies a default tax rate. This may result in incorrect tax classification. It's best practice to always assign an explicit tax code. **Q: Do I need to set a default tax behavior in Stripe?** In the Stripe dashboard, make sure that you have a default tax behavior selected to ensure tax is correctly added to each invoice. # Stripe Tax Source: https://docs.metronome.com/integrations/tax-integrations/stripe-tax Learn how to configure Stripe Tax with Metronome for automatic sales tax calculation on Stripe invoices. [Stripe Tax](https://docs.stripe.com/tax) is Stripe's native tax calculation engine. When configured, Stripe automatically calculates and applies sales tax to invoices that Metronome creates in Stripe. > [!NOTE] > > This page covers **Stripe Tax**—Stripe's own tax product. If you use **Anrok** or **Avalara** through the [Stripe Tax integration](https://docs.stripe.com/tax/third-party-apps), see [Anrok setup](/integrations/tax-integrations/anrok) or [Avalara setup](/integrations/tax-integrations/avalara). ## Prerequisites Before you begin: 1. [Activate and set up Stripe Tax](https://docs.stripe.com/tax/set-up) in your Stripe dashboard under **Settings > Tax**. 1. [Complete tax registration](https://docs.stripe.com/tax/registering) in the applicable jurisdictions for sales tax, VAT, and GST. 2. [Connect your Stripe account](/integrations/invoice-integrations/stripe) to Metronome. 3. Link each Metronome customer to their Stripe customer ID. 4. Ensure each Stripe customer has a [**Customer Address**](https://docs.stripe.com/api/customers/object#customer_object-address) set and is marked as **Taxable**. 5. Once you've completed initial setup, contact us via the [Metronome support portal](https://app.metronome.com/support) to enable tax application on your account. > [!NOTE] > > The Customer Address field is the `address` object on the [Stripe Customer object](https://docs.stripe.com/api/customers/object#customer_object-address), which determines tax jurisdiction. Failure to assign a Customer Address results in failure to apply tax. ## Step 1: Create Stripe products Stripe Tax uses the **product** on each invoice line item to [determine the applicable tax code](https://docs.stripe.com/tax/products-prices-tax-codes-tax-behavior) and rate. Create at least one Stripe product and assign the appropriate [tax code](https://docs.stripe.com/tax/tax-codes) to it in Stripe (under **Product Settings > Tax code**). You can map multiple Metronome products to the same Stripe product as long as they share the same tax code. Create additional Stripe products only when you need a different tax classification. > [!NOTE] > > If no tax code is specified on a product, Stripe Tax falls back to the account-level preset product tax code set under the **Preset product category** section in the [Stripe Dashboard](https://dashboard.stripe.com/settings/tax). ## Step 2: Create the Stripe Product ID custom field in Metronome Create a [custom field](/api-reference/custom-fields) on the **Product** entity in Metronome to store the Stripe product ID: 1. Go to **General Settings > Custom fields** (or use the Custom fields API). 2. Create a new custom field: * **Entity**: Product * **Key**: `stripe_product_id` 3. For each Metronome product, set the `stripe_product_id` value to the corresponding Stripe product ID (for example, `prod_ABC123`). > [!WARNING] > > **Do not** enable "Enforce uniqueness" (`enforce_uniqueness`). The same Stripe product ID is intentionally reused across multiple Metronome products. Enabling uniqueness can't be undone—you would need to archive the field and create a new one. ## Step 3: Configure entity mapping Set up the entity mapping so Metronome passes the product ID to Stripe on each invoice line item: 1. Go to **Developer > Integrations > Stripe > Edit Mapping**. 2. Add the following mapping: | Stripe vendor entity | Stripe vendor key | Metronome entity | Metronome key | | - | - | - | - | | `invoiceitem.price` | `product` | `ContractProduct` | `stripe_product_id` | 3. Click **Save**. **Optional: Additional entity mappings** If you need to pass additional metadata, you can add more mappings: | Metronome entity | Stripe entity | Use case | | - | - | - | | Product (any custom field) | `invoiceitem.metadata.*` | Pass line-item-level metadata (for example, `TaxCode`) | | Customer (any custom field) | `invoice.metadata.*` | Pass invoice-level metadata (for example, customer tax classification) | ## Test your configuration After completing tax setup: 1. Create a test customer in your sandbox environment with a valid Stripe customer. 2. Generate an invoice in Metronome. 3. Check the corresponding Stripe invoice to confirm tax has been calculated and applied. If tax isn't being calculated, verify: * Stripe Tax is [**enabled**](https://docs.stripe.com/tax/set-up) in your Stripe dashboard. * The Stripe customer has a **Customer Address** and is **Taxable**. * The entity mapping is saved and the `stripe_product_id` custom field has values set on your Metronome products. * The Stripe product has a valid [**tax code**](https://docs.stripe.com/tax/tax-codes) assigned. > [!NOTE] > > If automated tax isn't applying on the synced Stripe invoices, contact us via the [Metronome support portal](https://app.metronome.com/support). ## Threshold billing For customers using [prepaid balance thresholds](/guides/customers-billing/optimize-customer-experience/prepaid-balance-thresholds) or spend thresholds, tax is configured differently than for arrears invoices. > [!WARNING] > > The account-level tax enablement does **not** apply to threshold billing—you must explicitly set the tax type in the API. When setting up the `payment_gate_config`, specify `tax_type: "STRIPE"` and `"payment_type": "INVOICE"`: ```json theme={null} { "prepaid_balance_threshold_configuration": { "is_enabled": true, "threshold_amount": 500, "recharge_to_amount": 1500, "commit": { "product_id": "", "name": "Auto-recharge credits" }, "payment_gate_config": { "payment_gate_type": "STRIPE", "tax_type": "STRIPE", "stripe_config": { "payment_type": "INVOICE" } } } } ``` The same applies when adding one-off payment-gated commits through the edit contract endpoint. For spend thresholds, the configuration is similar: ```json theme={null} { "spend_threshold_configuration": { "is_enabled": true, "threshold_amount": 5000, "commit": { "product_id": "" }, "payment_gate_config": { "payment_gate_type": "STRIPE", "tax_type": "STRIPE", "stripe_config": { "payment_type": "INVOICE" } } } } ``` ## Settings that affect tax ### Collection method: charge\_automatically versus send\_invoice Both collection methods work with all tax providers. The collection method determines what happens after the invoice is finalized with tax: * `charge_automatically`—Stripe charges the customer's [default payment method](https://docs.stripe.com/api/customers/update#update_customer-invoice_settings-default_payment_method) on file. The customer must have a default payment method set in Stripe before the invoice is finalized, or payment will fail. The customer doesn't receive an invoice email by default (but you can enable [Successful Payments](https://docs.stripe.com/invoicing/automatic-charging) for receipt emails in Stripe). * `send_invoice`—Stripe emails the invoice to the customer with payment instructions. You must specify `days_until_due`. > [!NOTE] > > Tax is applied regardless of collection method. The choice between these methods is independent of your tax configuration. ### Leave invoices as drafts This setting (under **Developer > Integrations > Stripe > Settings**) controls whether Metronome immediately finalizes invoices in Stripe or leaves them as drafts. Stripe's [automatic tax](https://docs.stripe.com/tax) calculates tax inline when the invoice is finalized. It is generally recommended to switch this preference to **OFF** for automatic tax calculation upon invoice syncing. If you prefer to leave invoices as draft so you can review and finalize manually in Stripe, mark the "leave invoices as drafts" option in Metronome. ## FAQ and troubleshooting **Q: Can I reuse the same Stripe product for multiple Metronome products?** Yes, as long as they share the same [tax code](https://docs.stripe.com/tax/tax-codes). If your products are taxed differently, create separate Stripe products with different tax codes. **Q: Why is my threshold billing invoice not calculating tax?** The account-level tax enablement only applies to arrears invoices. For threshold billing, you must set `tax_type: "STRIPE"` in the `payment_gate_config` when creating or editing the contract. See the [Threshold billing](#threshold-billing) section above. **Q: My invoices are failing or are finalizing without tax -- what should I check?** The most common causes are a missing [Customer Address](https://docs.stripe.com/api/customers/object#customer_object-address) on the Stripe customer or an incomplete entity mapping in Metronome. Start by confirming that the Stripe customer has sufficient location information to accurately calculate tax rates for the customer. Next, check if the entity mapping is complete in Metronome. If both are verified and tax still isn't being applied, contact us via the [Metronome support portal](https://app.metronome.com/support) to check your account configuration. **Q: Do I need to set a default tax behavior in Stripe?** In the Stripe dashboard, make sure that you have a default tax behavior selected to ensure tax is correctly added to each invoice. # Archive a threshold notification Source: https://docs.metronome.com/api-reference/alerts/archive-a-threshold-notification /openapi.json post /v1/alerts/archive Permanently disable a threshold notification and remove it from active monitoring across all customers. Archived threshold notifications stop evaluating immediately and can optionally release their uniqueness key for reuse in future threshold notification configurations. ### Use this endpoint to: - Decommission threshold notifications that are no longer needed - Clean up test or deprecated threshold notification configurations - Free up uniqueness keys for reuse with new threshold notifications - Stop threshold notification evaluations without losing historical configuration data - Disable outdated monitoring rules during pricing model transitions ### Key response fields: - data: Object containing the archived threshold notification's ID ### Usage guidelines: - Irreversible for evaluation: Archived threshold notifications cannot be re-enabled; create a new threshold notification to resume monitoring - Uniqueness key handling: Set `release_uniqueness_key` : `true` to reuse the key in future threshold notifications - Immediate effect: Threshold notification evaluation stops instantly across all customers - Historical preservation: Archive operation maintains threshold notification history and configuration for compliance and auditing - Idempotent: Archiving an already-archived threshold notification returns the same successful response # Create a threshold notification Source: https://docs.metronome.com/api-reference/alerts/create-a-threshold-notification /openapi.json post /v1/alerts/create Create a new threshold notification to monitor customer spending, balances, and billing metrics in real-time. Metronome's notification system provides industry-leading speed with immediate evaluation capabilities, enabling you to proactively manage customer accounts and prevent revenue leakage. This endpoint creates configurable threshold notifications that continuously monitor various billing thresholds including spend limits, credit balances, commitment utilization, and invoice totals. Threshold notifications can be configured globally for all customers or targeted to specific customer accounts. ### Use this endpoint to: - Proactively monitor customer spending patterns to prevent unexpected overages or credit exhaustion - Automate notifications when customers approach commitment limits or credit thresholds - Enable real-time intervention for accounts at risk of churn or payment issues - Scale billing operations by automating threshold-based workflows and notifications ### Key response fields: A successful response returns a CustomerAlert object containing: - The threshold notification configuration with its unique ID and current status - The customer's evaluation status (ok, in_alarm, or evaluating) - Threshold notification metadata including type, threshold values, and update timestamps ### Usage guidelines: - Immediate evaluation: Set `evaluate_on_create` : `true` (default) for instant evaluation against existing customers - Uniqueness constraints: Each threshold notification must have a unique `uniqueness_key` within your organization. Use `release_uniqueness_key` : `true` when archiving to reuse keys - Notification type requirements: Different threshold notification types require specific fields (e.g., `billable_metric_id` for usage notifications, `credit_type_id` for credit-based threshold notifications) - Webhook delivery: Threshold notifications trigger webhook notifications for real-time integration with your systems. Configure webhook endpoints before creating threshold notifications - Performance at scale: Metronome's event-driven architecture processes threshold notification evaluations in real-time as usage events stream in, unlike competitors who rely on periodic polling or batch evaluation cycles # Get a threshold notification Source: https://docs.metronome.com/api-reference/alerts/get-a-threshold-notification /openapi.json post /v1/customer-alerts/get Retrieve the real-time evaluation status for a specific threshold notification-customer pair. This endpoint provides instant visibility into whether a customer has triggered a threshold notification condition, enabling you to monitor account health and take proactive action based on current threshold notification states. ### Use this endpoint to: - Check if a specific customer is currently violating an threshold notification (`in_alarm` status) - Verify threshold notification configuration details and threshold values for a customer - Monitor the evaluation state of newly created or recently modified threshold notification - Build dashboards or automated workflows that respond to specific threshold notification conditions - Validate threshold notification behavior before deploying to production customers - Integrate threshold notification status checks into customer support tools or admin interfaces ### Key response fields: A CustomerAlert object containing: - `customer_status`: The current evaluation state - `ok` - Customer is within acceptable thresholds - `in_alarm` - Customer has breached the threshold for the notification - `evaluating` - Notification is currently being evaluated (typically during initial setup) - `null` - Notification has been archived - `triggered_by`: Additional context about what caused the notification to trigger (when applicable) - `updated_at`: Timestamp of when the `customer_status` was last updated - alert: Complete threshold notification configuration including: - Notification ID, name, and type - Current threshold values and credit type information - Notification status (enabled, disabled, or archived) - Any applied filters (credit grant types, custom fields, group values) ### Usage guidelines: - Customer status: Returns the current evaluation state, not historical data. For threshold notification history, use webhook notifications or event logs - Required parameters: Both customer_id and alert_id must be valid UUIDs that exist in your organization - Archived notifications: Returns null for customer_status if the notification has been archived, but still includes the notification configuration details - Performance considerations: This endpoint queries live evaluation state, making it ideal for real-time monitoring but not for bulk status checks - Integration patterns: Best used for on-demand status checks in response to user actions or as part of targeted monitoring workflows - Error handling: Returns 404 if either the customer or alert_id doesn't exist or isn't accessible to your organization # Get all threshold notifications Source: https://docs.metronome.com/api-reference/alerts/get-all-threshold-notifications /openapi.json post /v1/customer-alerts/list Retrieve all threshold notification configurations and their current statuses for a specific customer in a single API call. This endpoint provides a comprehensive view of all threshold notification monitoring a customer account. ### Use this endpoint to: - Display all active threshold notifications for a customer in dashboards or admin panels - Quickly identify which threshold notifications a customer is currently triggering - Audit threshold notification coverage for specific accounts - Filter threshold notifications by status (enabled, disabled, or archived) ### Key response fields: - data: Array of CustomerAlert objects, each containing: - Current evaluation status (`ok`, `in_alarm`, `evaluating`, or `null`) - Complete threshold notification configuration and threshold details - Threshold notification metadata including type, name, and last update time - next_page: Pagination cursor for retrieving additional results ### Usage guidelines: - Default behavior: Returns only enabled threshold notifications unless `alert_statuses` filter is specified - Pagination: Use the `next_page` cursor to retrieve all results for customers with many notifications - Performance: Efficiently retrieves multiple threshold notification statuses in a single request instead of making individual calls - Filtering: Pass the `alert_statuses` array to include disabled or archived threshold notifications in results # Reset a threshold notification Source: https://docs.metronome.com/api-reference/alerts/reset-a-threshold-notification /openapi.json post /v1/customer-alerts/reset Force an immediate re-evaluation of a specific threshold notification for a customer, clearing any previous state and triggering a fresh assessment against current thresholds. This endpoint ensures threshold notification accuracy after configuration changes or data corrections. ### Use this endpoint to: - Clear false positive threshold notifications after fixing data issues - Re-evaluate threshold notifications after adjusting customer balances or credits - Test threshold notification behavior during development and debugging - Resolve stuck threshold notification that may be in an incorrect state - Trigger immediate evaluation after threshold modifications ### Key response fields: - 200 Success: Confirmation that the threshold notification has been reset and re-evaluation initiated - No response body is returned - the operation completes asynchronously ### Usage guidelines: - Immediate effect: Triggers re-evaluation instantly, which may result in new webhook notifications if thresholds are breached - State clearing: Removes any cached evaluation state, ensuring a fresh assessment - Use sparingly: Intended for exceptional cases, not routine operations - Asynchronous processing: The reset completes immediately, but re-evaluation happens in the background # Create a package Source: https://docs.metronome.com/api-reference/contracts/create-a-package /openapi.json post /v1/packages/create Create a package that defines a set of reusable, time-relative contract terms that can be used across cohorts of customers. Packages provide an abstraction layer on top of rate cards to provide an easy way to provision customers with standard pricing. ### **Use this endpoint to:** - Model standard pay-as-you-go pricing packages that can be easily reused across customers - Define standardized contract terms and discounting for sales-led motions - Set aliases for the package to facilitate easy package transition. Aliases are human-readable names that you can use in the place of the id of the package when provisioning a customer’s contract. By using an alias, you can easily create a contract and provision a customer by choosing the “Starter Plan” package, without storing the package ID in your internal systems. This is helpful when launching terms for a package, as you can create a new package with the “Starter Plan” alias scheduled to be assigned without updating your provisioning code. ### Key input fields: - `starting_at_offset`: Starting date relative to contract start. Generates the `starting_at` date when a contract is provisioned using a package. - `duration`: Duration starting from `starting_at_offset`. Generates the `ending_before` date when a contract is provisioned using a package. - `date_offset`: Date relative to contract start. Used for point-in-time dates without a duration. - `aliases`: Human-readable name to use when provisioning contracts with a package. ### Usage guidelines: - Use packages for standard self-serve use cases where customers have consistent terms. For customers with negotiated custom contract terms, use the `createContract` endpoint for maximum flexibility. - Billing provider configuration can be set when creating a package by using `billing_provider` and `delivery_method`. To provision a customer successfully with a package, the customer must have one and only one billing provider configuration that matches the billing provider configuration set on the package. - A package alias can only be used by one package at a time. If you create a new package with an alias that is already in use by another package, the original package’s alias schedule will be updated. The alias will reference the package to which it was most recently assigned. - Terms can only be specified using times relative to the contract start date. Supported granularities are: `days`, `weeks`, `months`, `years` - Packages cannot be edited once created. Use the rate card to easily add new rates across all of your customers or make direct edits to a contract after provisioning with a package. Edited contracts will still be associated with the package used during provisioning. # List contracts associated with a package Source: https://docs.metronome.com/api-reference/contracts/list-contracts-associated-with-a-package /openapi.json post /v1/packages/listContractsOnPackage For a given package, returns all contract IDs and customer IDs associated with the package over a specific time period. ### Use this endpoint to: - Understand which customers are provisioned on a package at any given time for internal cohort management - Manage customer migrations to a new package. For example, to migrate all active customers to a new package, call this endpoint, end contracts, and provision customers on a new package. ### **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. # 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. Adding or updating custom fields on credits, commits, or contracts does not emit `credit.edit`, `commit.edit`, or `contract.edit` events. # 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. # Void an invoice Source: https://docs.metronome.com/api-reference/invoices/void-an-invoice /openapi.json post /v1/invoices/void Permanently cancels an invoice by setting its status to voided, preventing collection and removing it from customer billing. Use this to correct billing errors, cancel incorrect charges, or handle disputed invoices that should not be collected. Returns the voided invoice ID with the status change applied immediately to stop any payment processing. # List all packages Source: https://docs.metronome.com/api-reference/list-all-packages /openapi.json post /v1/packages/list Lists all packages with details including name, aliases, duration, and terms. To view contracts on a specific package, use the `listContractsOnPackage` endpoint. # Archive an offset lifecycle event notification configuration Source: https://docs.metronome.com/api-reference/notifications/archive-an-offset-lifecycle-event-notification-configuration /openapi.json post /v2/notifications/archive Archive an offset lifecycle event notification configuration. Archived notifications are not processed. # Create an offset lifecycle event notification configuration Source: https://docs.metronome.com/api-reference/notifications/create-an-offset-lifecycle-event-notification-configuration /openapi.json post /v2/notifications/create Create an offset lifecycle event notification configuration. The lifecycle event type is inferred from the policy.type field. # Edit an offset or system notification Source: https://docs.metronome.com/api-reference/notifications/edit-an-offset-or-system-notification /openapi.json post /v2/notifications/edit Edit an existing offset notification, or enable/disable a system notification # Get an offset lifecycle event notification configuration Source: https://docs.metronome.com/api-reference/notifications/get-an-offset-lifecycle-event-notification-configuration /openapi.json post /v2/notifications/get Retrieve a specific offset lifecycle event notification configuration by ID. # List offset lifecycle event notification configurations Source: https://docs.metronome.com/api-reference/notifications/list-offset-lifecycle-event-notification-configurations /openapi.json post /v2/notifications/offset/list List offset lifecycle event notification configurations. These are user-created notifications that trigger at a specified time offset relative to lifecycle events. Returns a maximum of 400 results per request. # List system notification types Source: https://docs.metronome.com/api-reference/notifications/list-system-notification-types /openapi.json post /v2/notifications/system/list List available system notification types. You can enable these notifications directly or use supported types to create offset notifications. # Archive a package Source: https://docs.metronome.com/api-reference/packages/archive-a-package /openapi.json post /v1/packages/archive Archive a package. Archived packages cannot be used to create new contracts. However, existing contracts associated with the package will continue to function as normal. Once you archive a package, you can still retrieve it in the UI and API, but you cannot unarchive it. # Get a package Source: https://docs.metronome.com/api-reference/packages/get-a-package /openapi.json post /v1/packages/get Gets the details for a specific package, including name, aliases, duration, and terms. Use this endpoint to understand a package’s alias schedule, or display a specific package’s details to end customers. # Archive a product Source: https://docs.metronome.com/api-reference/products/archive-a-product /openapi.json post /v1/contract-pricing/products/archive Archive a product. Any current rate cards associated with this product will continue to function as normal. However, it will no longer be available as an option for newly created rates. Once you archive a product, you can still retrieve it in the UI and API, but you cannot unarchive it. # Create a product Source: https://docs.metronome.com/api-reference/products/create-a-product /openapi.json post /v1/contract-pricing/products/create Create a new product object. Products in Metronome represent your company's individual product or service offerings. A Product can be thought of as the basic unit of a line item on the invoice. This is analogous to SKUs or items in an ERP system. Give the product a meaningful name as they will appear on customer invoices. # Get a product Source: https://docs.metronome.com/api-reference/products/get-a-product /openapi.json post /v1/contract-pricing/products/get Retrieve a product by its ID, including all metadata and historical changes. # List products Source: https://docs.metronome.com/api-reference/products/list-products /openapi.json post /v1/contract-pricing/products/list Get a paginated list of all products in your organization with their complete configuration, version history, and metadata. By default excludes archived products unless explicitly requested via the `archive_filter` parameter. # Update a product Source: https://docs.metronome.com/api-reference/products/update-a-product /openapi.json post /v1/contract-pricing/products/update Updates a product's configuration while maintaining billing continuity for active customers. Use this endpoint to modify product names, metrics, pricing rules, and composite settings without disrupting ongoing billing cycles. Changes are scheduled using the starting_at timestamp, which must be on an hour boundary—set future dates to schedule updates ahead of time, or past dates for retroactive changes. Returns the updated product ID upon success. ### Usage guidance: - Product type cannot be changed after creation. For incorrect product types, create a new product and archive the original instead. # Add a rate Source: https://docs.metronome.com/api-reference/rate-cards/add-a-rate /openapi.json post /v1/contract-pricing/rate-cards/addRate Add a new rate This endpoint is heavily rate limited. For adding multiple rates, using the [addRates](https://docs.metronome.com/api-reference/rate-cards/add-rates) endpoint is strongly encouraged. # Add rates Source: https://docs.metronome.com/api-reference/rate-cards/add-rates /openapi.json post /v1/contract-pricing/rate-cards/addRates Add new rates # Archive a rate card Source: https://docs.metronome.com/api-reference/rate-cards/archive-a-rate-card /openapi.json post /v1/contract-pricing/rate-cards/archive Permanently disable a rate card by archiving it, preventing use in new contracts while preserving existing contract pricing. Use this when retiring old pricing models, consolidating rate cards, or removing outdated pricing structures. Returns the archived rate card ID and stops the rate card from appearing in contract creation workflows. # Create a rate card Source: https://docs.metronome.com/api-reference/rate-cards/create-a-rate-card /openapi.json post /v1/contract-pricing/rate-cards/create In Metronome, the rate card is the central location for your pricing. Rate cards were built with new product launches and pricing changes in mind - you can update your products and pricing in one place, and that change will be automatically propagated across your customer cohorts. Most clients need only maintain one or a few rate cards within Metronome. ### Use this endpoint to: - Create a rate card with a name and description - Define the rate card's single underlying fiat currency, and any number of conversion rates between that fiat currency and custom pricing units. You can then add products and associated rates in the fiat currency or custom pricing unit for which you have defined a conversion rate. - Set aliases for the rate card. Aliases are human-readable names that you can use in the place of the id of the rate card when provisioning a customer's contract. By using an alias, you can easily create a contract and provision a customer by choosing the paygo rate card, without storing the rate card id in your internal systems. This is helpful when launching a new rate card for paygo customers, you can update the alias for paygo to be scheduled to be assigned to the new rate card without updating your code. ### Key response fields: - The ID of the rate card you just created ### Usage guidelines: - After creating a rate card, you can now use the addRate or addRates endpoints to add products and their prices to it - A rate card alias can only be used by one rate card at a time. If you create a contract with a rate card alias that is already in use by another rate card, the original rate card's alias schedule will be updated. The alias will reference the rate card to which it was most recently assigned. # Get a rate card Source: https://docs.metronome.com/api-reference/rate-cards/get-a-rate-card /openapi.json post /v1/contract-pricing/rate-cards/get Return details for a specific rate card including name, description, and aliases. This endpoint does not return rates - use the dedicated getRates or getRateSchedule endpoints to understand the rates on a rate card. # Get a rate schedule Source: https://docs.metronome.com/api-reference/rate-cards/get-a-rate-schedule /openapi.json post /v1/contract-pricing/rate-cards/getRateSchedule A rate card defines the prices that you charge for your products. Rate cards support scheduled changes over time, to allow you to easily roll out pricing changes and new product launches across your customer base. Use this endpoint to understand the rate schedule `starting_at` a given date, optionally filtering the list of rates returned based on product id or pricing group values. For example, you may want to display a schedule of upcoming price changes for a given product in your product experience - use this endpoint to fetch that information from its source of truth in Metronome. If you want to understand the rates for a specific customer's contract, inclusive of contract-level overrides, use the `getContractRateSchedule` endpoint. # Get rates Source: https://docs.metronome.com/api-reference/rate-cards/get-rates /openapi.json post /v1/contract-pricing/rate-cards/getRates Understand the rate schedule at a given timestamp, optionally filtering the list of rates returned based on properties such as `product_id` and `pricing_group_values`. For example, you may want to display the current price for a given product in your product experience - use this endpoint to fetch that information from its source of truth in Metronome. If you want to understand the rates for a specific customer's contract, inclusive of contract-level overrides, use the `getContractRateSchedule` endpoint. # List rate cards Source: https://docs.metronome.com/api-reference/rate-cards/list-rate-cards /openapi.json post /v1/contract-pricing/rate-cards/list List all rate cards. Returns rate card IDs, names, descriptions, aliases, and other details. To view the rates associated with a given rate card, use the getRates or getRateSchedule endpoints. # Set the rate card products order Source: https://docs.metronome.com/api-reference/rate-cards/set-the-rate-card-products-order /openapi.json post /v1/contract-pricing/rate-cards/setRateCardProductsOrder The ordering of products on a rate card determines the order in which the products will appear on customers' invoices. Use this endpoint to set the order of products on the rate card. # Update a rate card Source: https://docs.metronome.com/api-reference/rate-cards/update-a-rate-card /openapi.json post /v1/contract-pricing/rate-cards/update Update a rate card's name, description, aliases, and credit type conversion rates. This endpoint does not affect underlying pricing rates or schedules. ### Use this endpoint to: - Rename rate cards: Update display names or descriptions for organizational clarity - Manage aliases: Add, modify, or schedule alias transitions for seamless and code-free rate card migrations - Update documentation: Keep rate card descriptions current with business context - Configure custom pricing units: Add credit type conversions to enable rates with different pricing units #### Active contract impact: - Alias changes: Already-created contracts continue using their originally assigned rate cards. - Other changes made using this endpoint will only impact the Metronome UI. #### Grandfathering existing PLG customer pricing: - Rate card aliases support scheduled transitions, enabling seamless rate card migrations for new customers, allowing existing customers to be grandfathered into their existing prices without code. Note that there are multiple mechanisms to support grandfathering in Metronome. #### How scheduled aliases work for PLG grandfathering: Initial setup: - Add alias to current rate card: Assign a stable alias (e.g., "standard-pricing") to your active rate card - Reference alias during contract creation: Configure your self-serve workflow to create contracts using `rate_card_alias` instead of direct `rate_card_id` - Automatic resolution: New contracts referencing the alias automatically resolve to the rate card associated with the alias at the point in time of provisioning #### Grandfathering process: - Create new rate card: Build your new rate card with updated pricing structure - Schedule alias transition: Add the same alias to the new rate card with a `starting_at` timestamp - Automatic cutover: Starting at the scheduled time, new contracts created in your PLG workflow using that alias will automatically reference the new rate card # Update the rate card products order Source: https://docs.metronome.com/api-reference/rate-cards/update-the-rate-card-products-order /openapi.json post /v1/contract-pricing/rate-cards/moveRateCardProducts The ordering of products on a rate card determines the order in which the products will appear on customers' invoices. Use this endpoint to set the order of specific products on the rate card by moving them relative to their current location. # Get audit logs Source: https://docs.metronome.com/api-reference/security/get-audit-logs /openapi.json get /v1/auditLogs Get a comprehensive audit trail of all operations performed in your Metronome account, whether initiated through the API, web interface, or automated processes. This endpoint provides detailed logs of who did what and when, enabling compliance reporting, security monitoring, and operational troubleshooting across all interaction channels. ### Use this endpoint to: - Monitor all account activity for security and compliance purposes - Track configuration changes regardless of source (API, UI, or system) - Investigate issues by reviewing historical operations ### Key response fields: An array of AuditLog objects containing: - id: Unique identifier for the audit log entry - timestamp: When the action occurred (RFC 3339 format) - actor: Information about who performed the action - request: Details including request ID, IP address, and user agent - `resource_type`: The type of resource affected (e.g., customer, contract, invoice) - `resource_id`: The specific resource identifier - `action`: The operation performed - `next_page`: Cursor for continuous log retrieval ### Usage guidelines: - Continuous retrieval: The next_page token enables uninterrupted log streaming—save it between requests to ensure no logs are missed - Empty responses: An empty data array means no new logs yet; continue polling with the same next_page token - Date filtering: - `starting_on`: Earliest logs to return (inclusive) - `ending_before`: Latest logs to return (exclusive) - Cannot be used with `next_page` - Resource filtering: Must specify both `resource_type` and `resource_id` together - Sort order: Default is `date_asc`; use `date_desc` for newest first # Get services Source: https://docs.metronome.com/api-reference/security/get-services /openapi.json get /v1/services Gets Metronome's service registry with associated IP addresses for security allowlisting and firewall configuration. Use this endpoint to maintain an up-to-date list of IPs that your systems should trust for Metronome communications. Returns service names and their current IP ranges, with new IPs typically appearing 30+ days before first use to ensure smooth allowlist updates. # Archive a pricing unit Source: https://docs.metronome.com/api-reference/settings/archive-a-pricing-unit /openapi.json post /v1/credit-types/archive Archive a custom pricing unit. Once archived, it will no longer appear in pricing unit selectors by default. # Create a pricing unit Source: https://docs.metronome.com/api-reference/settings/create-a-pricing-unit /openapi.json post /v1/credit-types/create Create a custom pricing unit. Custom pricing units can be used to charge for usage in a non-fiat pricing unit, for example AI credits. # List account-level billing providers Source: https://docs.metronome.com/api-reference/settings/list-account-level-billing-providers /openapi.json post /v1/listConfiguredBillingProviders Lists all configured billing providers and their delivery method configurations for your account. Returns provider details, delivery method IDs, and configuration settings needed for mapping individual customer contracts to billing integrations. # List pricing units Source: https://docs.metronome.com/api-reference/settings/list-pricing-units /openapi.json get /v1/credit-types/list List all pricing units. All fiat currency types (for example, USD or GBP) will be included, as well as any custom pricing units that were configured. Custom pricing units can be used to charge for usage in a non-fiat pricing unit, for example AI credits. Note: The USD (cents) pricing unit is 2714e483-4ff1-48e4-9e25-ac732e8f24f2. # Set up account-level billing provider Source: https://docs.metronome.com/api-reference/settings/set-up-account-level-billing-provider /openapi.json post /v1/setUpBillingProvider Set up account-level configuration for a billing provider. Once configured, individual contracts across customers can be mapped to this configuration using the returned delivery_method_id. # Upsert Anrok API token Source: https://docs.metronome.com/api-reference/settings/upsert-anrok-api-token /openapi.json post /v1/upsertAnrokApiToken Set the Anrok API token for some specified delivery_method_ids, which can be found in the `/listConfiguredBillingProviders` response. This maps the Anrok key to the appropriate billing entity. These API tokens are only used for Threshold Billing workflows today. # Upsert Avalara credentials Source: https://docs.metronome.com/api-reference/settings/upsert-avalara-credentials /openapi.json post /v1/upsertAvalaraCredentials Set the Avalara credentials for some specified `delivery_method_ids`, which can be found in the `/listConfiguredBillingProviders` response. This maps the Avalara credentials to the appropriate billing entity. These credentials are only used for PLG Invoicing today. # Get batched usage data Source: https://docs.metronome.com/api-reference/usage/get-batched-usage-data /openapi.json post /v1/usage Retrieve aggregated usage data across multiple customers and billable metrics in a single query. This batch endpoint enables you to fetch usage patterns at scale, broken down by time windows, making it ideal for building analytics dashboards, generating reports, and monitoring platform-wide usage trends. ### Use this endpoint to: - Generate platform-wide usage reports for internal teams - Monitor aggregate usage trends across your entire customer base - Create comparative usage analyses between customers or time periods - Support capacity planning with historical usage patterns ### Key response fields: An array of `UsageBatchAggregate` objects containing: - `customer_id`: The customer this usage belongs to - `billable_metric_id` and `billable_metric_name`: What was measured - `start_timestamp` and `end_timestamp`: Time window for this data point - `value`: Aggregated usage amount for the period - `groups` (optional): Usage broken down by group keys with values - `next_page`: Pagination cursor for large result sets ### Usage guidelines: - Time windows: Set `window_size` to `hour`, `day`, or `none` (entire period) - Required parameters: Must specify `starting_on`, `ending_before`, and `window_size` - Filtering options: - `customer_ids`: Limit to specific customers (omit for all customers) - `billable_metrics`: Limit to specific metrics (omit for all metrics) - Pagination: Use `next_page` cursor to retrieve large datasets - Null values: Group values may be null when no usage matches that group # Get usage data with paginated groupings Source: https://docs.metronome.com/api-reference/usage/get-usage-data-with-paginated-groupings /openapi.json post /v1/usage/groups Retrieve granular usage data for a specific customer and billable metric, with the ability to break down usage by custom grouping dimensions. This endpoint enables deep usage analytics by segmenting data across attributes like region, user, model type, or any custom dimension defined in your billable metrics. ### Use this endpoint to: - Analyze usage patterns broken down by specific attributes (region, user, department, etc.) - Build detailed usage dashboards with dimensional filtering - Identify high-usage segments for optimization opportunities ### Request parameters Use [`group_key`](#body-group-key) and [`group_filters`](#body-group-filters) to group by one or more dimensions. This is required for compound group keys and recommended for all new integrations: ```json { "group_key": ["region", "team"], "group_filters": { "region": ["US-East", "US-West"] } } ``` Important: For compound group keys, you must pass the complete set of keys that make up the compound key. Partial key combinations are not supported. For example, if your billable metric has a compound group key `[region, team, environment]`, you must pass all three keys in group_key—you cannot pass just `[region]` or `[region, team]`. ### Key response fields: An array of `PagedUsageAggregate` objects containing: - `starting_on` and `ending_before`: Time window boundaries - `group`: Object mapping group keys to their values - For simple groups, this will be a map with a single key-value pair (e.g., `{"region": "US-East"}`) - For compound groups, this will be a map with multiple key-value pairs (e.g., `{"region": "US-East", "team": "engineering"}`) - `value`: Aggregated usage for this group and time window - `next_page`: Pagination cursor for large datasets ### Usage guidelines: - Required parameters: Must specify `customer_id`, `billable_metric_id`, and `window_size` - Time windows: Set `window_size` to hour, day, or none for different granularities - Group filtering: Use `group_key` and `group_filters` to specify groups and group filters. Across all arrays in `group_filters`, include at most 200 filter values total. Requests with more than 200 filter values are rejected when this limit is enforced - Response limit: When using compound group keys (2+ keys in `group_key`), the default and maximum page size is 100 - Pagination: Use limit and `next_page` for large result sets - Null handling: Group values may be null for events missing the group key property # Ingest events Source: https://docs.metronome.com/api-reference/usage/ingest-events /openapi.json post /v1/ingest The ingest endpoint is the primary method for sending usage events to Metronome, serving as the foundation for all billing calculations in your usage-based pricing model. This high-throughput endpoint is designed for real-time streaming ingestion, supports backdating 34 days, and is built to handle mission-critical usage data with enterprise-grade reliability. Metronome supports 100,000 events per second without requiring pre-aggregation or rollups and can scale up from there. See the [Send usage events](/guides/events/send-usage-events) guide to learn more about usage events. ### Use this endpoint to: Create a customer usage pipeline into Metronome that drives billable metrics, credit drawdown, and invoicing. Track customer behavior, resource consumption, and feature usage ### What happens when you send events: - Events are validated and processed in real-time - Events are matched to customers using customer IDs or customer ingest aliases - Events are matched to billable metrics and are immediately available for usage and spend calculations ### Usage guidelines: - Historical events can be backdated up to 34 days and will immediately impact live customer spend - Duplicate events are automatically detected and ignored (34-day deduplication window) #### Event structure: Usage events are simple JSON objects designed for flexibility and ease of integration: ```json { "transaction_id": "2021-01-01T00:00:00Z_cluster42", "customer_id": "team@example.com", "event_type": "api_request", "timestamp": "2021-01-01T00:00:00Z", "properties": { "endpoint": "/v1/users", "method": "POST", "response_time_ms": 45, "region": "us-west-2" } } ``` Learn more about [usage event structure definitions](/guides/events/design-usage-events). #### Transaction ID The transaction_id serves as your idempotency key, ensuring events are processed exactly once. Metronome maintains a 34-day deduplication window - significantly longer than typical 12-hour windows - enabling robust backfill scenarios without duplicate billing. - Best Practices: - Use UUIDs for one-time events: uuid4() - For heartbeat events, use deterministic IDs - Include enough context to avoid collisions across different event sources #### Customer ID Identifies which customer should be billed for this usage. Supports two identification methods: - Metronome Customer ID: The UUID returned when creating a customer - Ingest Alias: Your system's identifier (email, account number, etc.) Ingest aliases enable seamless integration without requiring ID mapping, and customers can have multiple aliases for flexibility. #### Event Type: Categorizes the event type for billable metric matching. Choose descriptive names that aligns with the product surface area. #### Properties: Flexible metadata also used to match billable metrics or to be used to serve as group keys to create multiple pricing dimensions or breakdown costs by novel properties for end customers or internal finance teams measuring underlying COGs. # Search events Source: https://docs.metronome.com/api-reference/usage/search-events /openapi.json post /v1/events/search This endpoint retrieves events by transaction ID for events that occurred within the last 34 days. It is specifically designed for sampling-based testing workflows to detect revenue leakage. The Event Search API provides a critical observability tool that validates the integrity of your usage pipeline by allowing you to sample raw events and verify their matching against active billable metrics. Why event observability matters for revenue leakage: Silent revenue loss occurs when events are dropped, delayed, or fail to match billable metrics due to: - Upstream system failures - Event format changes - Misconfigured billable metrics ### Use this endpoint to: - Sample raw events and validate they match the expected billable metrics - Build custom leakage detection alerts to prevent silent revenue loss - Verify event processing accuracy during system changes or metric updates - Debug event matching issues in real-time ### Key response fields: - Complete event details including transaction ID, customer ID, and properties - Matched Metronome customer (if any) - Matched billable metric information (if any) - Processing status and duplicate detection flags ### Usage guidelines: ⚠️ Important: This endpoint is heavily rate limited and designed for sampling workflows only. Do not use this endpoint to check every event in your system. Instead, implement a sampling strategy to randomly validate a subset of events for observability purposes. # Get Triggered Notification and Delivery Attempts Source: https://docs.metronome.com/api-reference/webhooks/get-triggered-notification-and-delivery-attempts /openapi.json get /v1/webhooks/{webhook_id}/triggered_notifications/{triggered_notification_id} List all delivery attempts for a triggered notification to a specific webhook destination. Use this endpoint to debug webhook delivery issues programmatically by viewing the payload and number of retries for a specific triggered notification. ### Key response fields: - Notification payload for the specific triggered notification - Array of all attempts to the webhook destination for the triggered notification, including attempt timestamp and status code ### Usage guidelines: - Triggered notification ID is distinct from notification ID. Notification ID represents the notification configuration (“notify me when any customer reaches \$5 in credit balance”). Triggered notification ID is the specific instance when that notification was triggered (”Customer A’s credit balance reached \$5 on October 5th at 11:45 PM”). - Use this endpoint in conjunction with [List Triggered Notifications](/api-reference/webhooks/list-triggered-notifications-by-webhook) to identify the specific triggered notification ID to pass in.. # List triggered notifications by webhook Source: https://docs.metronome.com/api-reference/webhooks/list-triggered-notifications-by-webhook /openapi.json post /v1/webhooks/{webhook_id}/triggered_notifications Retrieve all triggered notifications with delivery attempts to a webhook destination, with flexible filtering options to monitor, audit, and debug notification history. Results are ordered by the time of the first delivery attempt and limited to the most recent 30 days. ### Use this endpoint to: - Identify whether notifications were triggered and delivered to webhook destinations when expected to debug issues - Understand and audit the timeline of triggered notifications - Monitor webhook destination health ### Key response fields: Array of triggered notifications containing: - ID of the specific triggered notification - Webhook destination ID - Customer ID - Notification configuration ID and type - `first_attempted_at`: Timestamp of the first delivery attempt to the webhook destination - `last_attempted_at`: Timestamp of the latest delivery attempt - Latest response status code - Number of total delivery attempts to the webhook destination ### Usage guidelines: - Use filters to narrow down results and reduce pagination - Use the `notification_ids` filter to investigate triggered notifications for a specific notification configuration. Pass the configuration's ID (e.g., `8deed800-1b7a-495d-a207-6c52bac54dc9`), available as `notification_id` in delivery responses. - Filter for system notifications using notification type rather than notification ID - Use the [Get Triggered Notification and Delivery Attempts](/api-reference/webhooks/get-triggered-notification-and-delivery-attempts) endpoint to understand the total retry attempts for a specific triggered notification # Archive a threshold notification Source: https://docs.metronome.com/api-reference/alerts/archive-a-threshold-notification /openapi.json post /v1/alerts/archive Permanently disable a threshold notification and remove it from active monitoring across all customers. Archived threshold notifications stop evaluating immediately and can optionally release their uniqueness key for reuse in future threshold notification configurations. ### Use this endpoint to: - Decommission threshold notifications that are no longer needed - Clean up test or deprecated threshold notification configurations - Free up uniqueness keys for reuse with new threshold notifications - Stop threshold notification evaluations without losing historical configuration data - Disable outdated monitoring rules during pricing model transitions ### Key response fields: - data: Object containing the archived threshold notification's ID ### Usage guidelines: - Irreversible for evaluation: Archived threshold notifications cannot be re-enabled; create a new threshold notification to resume monitoring - Uniqueness key handling: Set `release_uniqueness_key` : `true` to reuse the key in future threshold notifications - Immediate effect: Threshold notification evaluation stops instantly across all customers - Historical preservation: Archive operation maintains threshold notification history and configuration for compliance and auditing - Idempotent: Archiving an already-archived threshold notification returns the same successful response # Create a threshold notification Source: https://docs.metronome.com/api-reference/alerts/create-a-threshold-notification /openapi.json post /v1/alerts/create Create a new threshold notification to monitor customer spending, balances, and billing metrics in real-time. Metronome's notification system provides industry-leading speed with immediate evaluation capabilities, enabling you to proactively manage customer accounts and prevent revenue leakage. This endpoint creates configurable threshold notifications that continuously monitor various billing thresholds including spend limits, credit balances, commitment utilization, and invoice totals. Threshold notifications can be configured globally for all customers or targeted to specific customer accounts. ### Use this endpoint to: - Proactively monitor customer spending patterns to prevent unexpected overages or credit exhaustion - Automate notifications when customers approach commitment limits or credit thresholds - Enable real-time intervention for accounts at risk of churn or payment issues - Scale billing operations by automating threshold-based workflows and notifications ### Key response fields: A successful response returns a CustomerAlert object containing: - The threshold notification configuration with its unique ID and current status - The customer's evaluation status (ok, in_alarm, or evaluating) - Threshold notification metadata including type, threshold values, and update timestamps ### Usage guidelines: - Immediate evaluation: Set `evaluate_on_create` : `true` (default) for instant evaluation against existing customers - Uniqueness constraints: Each threshold notification must have a unique `uniqueness_key` within your organization. Use `release_uniqueness_key` : `true` when archiving to reuse keys - Notification type requirements: Different threshold notification types require specific fields (e.g., `billable_metric_id` for usage notifications, `credit_type_id` for credit-based threshold notifications) - Webhook delivery: Threshold notifications trigger webhook notifications for real-time integration with your systems. Configure webhook endpoints before creating threshold notifications - Performance at scale: Metronome's event-driven architecture processes threshold notification evaluations in real-time as usage events stream in, unlike competitors who rely on periodic polling or batch evaluation cycles # Get a threshold notification Source: https://docs.metronome.com/api-reference/alerts/get-a-threshold-notification /openapi.json post /v1/customer-alerts/get Retrieve the real-time evaluation status for a specific threshold notification-customer pair. This endpoint provides instant visibility into whether a customer has triggered a threshold notification condition, enabling you to monitor account health and take proactive action based on current threshold notification states. ### Use this endpoint to: - Check if a specific customer is currently violating an threshold notification (`in_alarm` status) - Verify threshold notification configuration details and threshold values for a customer - Monitor the evaluation state of newly created or recently modified threshold notification - Build dashboards or automated workflows that respond to specific threshold notification conditions - Validate threshold notification behavior before deploying to production customers - Integrate threshold notification status checks into customer support tools or admin interfaces ### Key response fields: A CustomerAlert object containing: - `customer_status`: The current evaluation state - `ok` - Customer is within acceptable thresholds - `in_alarm` - Customer has breached the threshold for the notification - `evaluating` - Notification is currently being evaluated (typically during initial setup) - `null` - Notification has been archived - `triggered_by`: Additional context about what caused the notification to trigger (when applicable) - `updated_at`: Timestamp of when the `customer_status` was last updated - alert: Complete threshold notification configuration including: - Notification ID, name, and type - Current threshold values and credit type information - Notification status (enabled, disabled, or archived) - Any applied filters (credit grant types, custom fields, group values) ### Usage guidelines: - Customer status: Returns the current evaluation state, not historical data. For threshold notification history, use webhook notifications or event logs - Required parameters: Both customer_id and alert_id must be valid UUIDs that exist in your organization - Archived notifications: Returns null for customer_status if the notification has been archived, but still includes the notification configuration details - Performance considerations: This endpoint queries live evaluation state, making it ideal for real-time monitoring but not for bulk status checks - Integration patterns: Best used for on-demand status checks in response to user actions or as part of targeted monitoring workflows - Error handling: Returns 404 if either the customer or alert_id doesn't exist or isn't accessible to your organization # Get all threshold notifications Source: https://docs.metronome.com/api-reference/alerts/get-all-threshold-notifications /openapi.json post /v1/customer-alerts/list Retrieve all threshold notification configurations and their current statuses for a specific customer in a single API call. This endpoint provides a comprehensive view of all threshold notification monitoring a customer account. ### Use this endpoint to: - Display all active threshold notifications for a customer in dashboards or admin panels - Quickly identify which threshold notifications a customer is currently triggering - Audit threshold notification coverage for specific accounts - Filter threshold notifications by status (enabled, disabled, or archived) ### Key response fields: - data: Array of CustomerAlert objects, each containing: - Current evaluation status (`ok`, `in_alarm`, `evaluating`, or `null`) - Complete threshold notification configuration and threshold details - Threshold notification metadata including type, name, and last update time - next_page: Pagination cursor for retrieving additional results ### Usage guidelines: - Default behavior: Returns only enabled threshold notifications unless `alert_statuses` filter is specified - Pagination: Use the `next_page` cursor to retrieve all results for customers with many notifications - Performance: Efficiently retrieves multiple threshold notification statuses in a single request instead of making individual calls - Filtering: Pass the `alert_statuses` array to include disabled or archived threshold notifications in results # Reset a threshold notification Source: https://docs.metronome.com/api-reference/alerts/reset-a-threshold-notification /openapi.json post /v1/customer-alerts/reset Force an immediate re-evaluation of a specific threshold notification for a customer, clearing any previous state and triggering a fresh assessment against current thresholds. This endpoint ensures threshold notification accuracy after configuration changes or data corrections. ### Use this endpoint to: - Clear false positive threshold notifications after fixing data issues - Re-evaluate threshold notifications after adjusting customer balances or credits - Test threshold notification behavior during development and debugging - Resolve stuck threshold notification that may be in an incorrect state - Trigger immediate evaluation after threshold modifications ### Key response fields: - 200 Success: Confirmation that the threshold notification has been reset and re-evaluation initiated - No response body is returned - the operation completes asynchronously ### Usage guidelines: - Immediate effect: Triggers re-evaluation instantly, which may result in new webhook notifications if thresholds are breached - State clearing: Removes any cached evaluation state, ensuring a fresh assessment - Use sparingly: Intended for exceptional cases, not routine operations - Asynchronous processing: The reset completes immediately, but re-evaluation happens in the background # 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://app.metronome.com/support) 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://app.metronome.com/support) 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 a page of 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. ### Usage guidelines: - Pagination: Results are limited to 20 contracts per page; use 'cursor' for more ⚠️ 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 a page 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. Results are limited to 20 contracts per page. When the response includes a non-null `cursor`, pass it back as the `cursor` parameter to fetch the next page. # 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. # 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. Adding or updating custom fields on credits, commits, or contracts does not emit `credit.edit`, `commit.edit`, or `contract.edit` events. # 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. # 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. # Void an invoice Source: https://docs.metronome.com/api-reference/invoices/void-an-invoice /openapi.json post /v1/invoices/void Permanently cancels an invoice by setting its status to voided, preventing collection and removing it from customer billing. Use this to correct billing errors, cancel incorrect charges, or handle disputed invoices that should not be collected. Returns the voided invoice ID with the status change applied immediately to stop any payment processing. # Create an offset lifecycle event notification configuration Source: https://docs.metronome.com/api-reference/notifications/create-an-offset-lifecycle-event-notification-configuration /openapi.json post /v2/notifications/create Create an offset lifecycle event notification configuration. The lifecycle event type is inferred from the policy.type field. # Edit an offset or system notification Source: https://docs.metronome.com/api-reference/notifications/edit-an-offset-or-system-notification /openapi.json post /v2/notifications/edit Edit an existing offset notification, or enable/disable a system notification # Get an offset lifecycle event notification configuration Source: https://docs.metronome.com/api-reference/notifications/get-an-offset-lifecycle-event-notification-configuration /openapi.json post /v2/notifications/get Retrieve a specific offset lifecycle event notification configuration by ID. # List offset lifecycle event notification configurations Source: https://docs.metronome.com/api-reference/notifications/list-offset-lifecycle-event-notification-configurations /openapi.json post /v2/notifications/offset/list List offset lifecycle event notification configurations. These are user-created notifications that trigger at a specified time offset relative to lifecycle events. Returns a maximum of 400 results per request. # List system notification types Source: https://docs.metronome.com/api-reference/notifications/list-system-notification-types /openapi.json post /v2/notifications/system/list List available system notification types. You can enable these notifications directly or use supported types to create offset notifications. # Create a package Source: https://docs.metronome.com/api-reference/contracts/create-a-package /openapi.json post /v1/packages/create Create a package that defines a set of reusable, time-relative contract terms that can be used across cohorts of customers. Packages provide an abstraction layer on top of rate cards to provide an easy way to provision customers with standard pricing. ### **Use this endpoint to:** - Model standard pay-as-you-go pricing packages that can be easily reused across customers - Define standardized contract terms and discounting for sales-led motions - Set aliases for the package to facilitate easy package transition. Aliases are human-readable names that you can use in the place of the id of the package when provisioning a customer’s contract. By using an alias, you can easily create a contract and provision a customer by choosing the “Starter Plan” package, without storing the package ID in your internal systems. This is helpful when launching terms for a package, as you can create a new package with the “Starter Plan” alias scheduled to be assigned without updating your provisioning code. ### Key input fields: - `starting_at_offset`: Starting date relative to contract start. Generates the `starting_at` date when a contract is provisioned using a package. - `duration`: Duration starting from `starting_at_offset`. Generates the `ending_before` date when a contract is provisioned using a package. - `date_offset`: Date relative to contract start. Used for point-in-time dates without a duration. - `aliases`: Human-readable name to use when provisioning contracts with a package. ### Usage guidelines: - Use packages for standard self-serve use cases where customers have consistent terms. For customers with negotiated custom contract terms, use the `createContract` endpoint for maximum flexibility. - Billing provider configuration can be set when creating a package by using `billing_provider` and `delivery_method`. To provision a customer successfully with a package, the customer must have one and only one billing provider configuration that matches the billing provider configuration set on the package. - A package alias can only be used by one package at a time. If you create a new package with an alias that is already in use by another package, the original package’s alias schedule will be updated. The alias will reference the package to which it was most recently assigned. - Terms can only be specified using times relative to the contract start date. Supported granularities are: `days`, `weeks`, `months`, `years` - Packages cannot be edited once created. Use the rate card to easily add new rates across all of your customers or make direct edits to a contract after provisioning with a package. Edited contracts will still be associated with the package used during provisioning. # List contracts associated with a package Source: https://docs.metronome.com/api-reference/contracts/list-contracts-associated-with-a-package /openapi.json post /v1/packages/listContractsOnPackage For a given package, returns all contract IDs and customer IDs associated with the package over a specific time period. ### Use this endpoint to: - Understand which customers are provisioned on a package at any given time for internal cohort management - Manage customer migrations to a new package. For example, to migrate all active customers to a new package, call this endpoint, end contracts, and provision customers on a new package. ### **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. # List all packages Source: https://docs.metronome.com/api-reference/list-all-packages /openapi.json post /v1/packages/list Lists all packages with details including name, aliases, duration, and terms. To view contracts on a specific package, use the `listContractsOnPackage` endpoint. # Archive an offset lifecycle event notification configuration Source: https://docs.metronome.com/api-reference/notifications/archive-an-offset-lifecycle-event-notification-configuration /openapi.json post /v2/notifications/archive Archive an offset lifecycle event notification configuration. Archived notifications are not processed. # Archive a package Source: https://docs.metronome.com/api-reference/packages/archive-a-package /openapi.json post /v1/packages/archive Archive a package. Archived packages cannot be used to create new contracts. However, existing contracts associated with the package will continue to function as normal. Once you archive a package, you can still retrieve it in the UI and API, but you cannot unarchive it. # Get a package Source: https://docs.metronome.com/api-reference/packages/get-a-package /openapi.json post /v1/packages/get Gets the details for a specific package, including name, aliases, duration, and terms. Use this endpoint to understand a package’s alias schedule, or display a specific package’s details to end customers. # Archive a product Source: https://docs.metronome.com/api-reference/products/archive-a-product /openapi.json post /v1/contract-pricing/products/archive Archive a product. Any current rate cards associated with this product will continue to function as normal. However, it will no longer be available as an option for newly created rates. Once you archive a product, you can still retrieve it in the UI and API, but you cannot unarchive it. # Create a product Source: https://docs.metronome.com/api-reference/products/create-a-product /openapi.json post /v1/contract-pricing/products/create Create a new product object. Products in Metronome represent your company's individual product or service offerings. A Product can be thought of as the basic unit of a line item on the invoice. This is analogous to SKUs or items in an ERP system. Give the product a meaningful name as they will appear on customer invoices. # Get a product Source: https://docs.metronome.com/api-reference/products/get-a-product /openapi.json post /v1/contract-pricing/products/get Retrieve a product by its ID, including all metadata and historical changes. # List products Source: https://docs.metronome.com/api-reference/products/list-products /openapi.json post /v1/contract-pricing/products/list Get a paginated list of all products in your organization with their complete configuration, version history, and metadata. By default excludes archived products unless explicitly requested via the `archive_filter` parameter. # Update a product Source: https://docs.metronome.com/api-reference/products/update-a-product /openapi.json post /v1/contract-pricing/products/update Updates a product's configuration while maintaining billing continuity for active customers. Use this endpoint to modify product names, metrics, pricing rules, and composite settings without disrupting ongoing billing cycles. Changes are scheduled using the starting_at timestamp, which must be on an hour boundary—set future dates to schedule updates ahead of time, or past dates for retroactive changes. Returns the updated product ID upon success. ### Usage guidance: - Product type cannot be changed after creation. For incorrect product types, create a new product and archive the original instead. # Add a rate Source: https://docs.metronome.com/api-reference/rate-cards/add-a-rate /openapi.json post /v1/contract-pricing/rate-cards/addRate Add a new rate This endpoint is heavily rate limited. For adding multiple rates, using the [addRates](https://docs.metronome.com/api-reference/rate-cards/add-rates) endpoint is strongly encouraged. # Add rates Source: https://docs.metronome.com/api-reference/rate-cards/add-rates /openapi.json post /v1/contract-pricing/rate-cards/addRates Add new rates # Archive a rate card Source: https://docs.metronome.com/api-reference/rate-cards/archive-a-rate-card /openapi.json post /v1/contract-pricing/rate-cards/archive Permanently disable a rate card by archiving it, preventing use in new contracts while preserving existing contract pricing. Use this when retiring old pricing models, consolidating rate cards, or removing outdated pricing structures. Returns the archived rate card ID and stops the rate card from appearing in contract creation workflows. # Create a rate card Source: https://docs.metronome.com/api-reference/rate-cards/create-a-rate-card /openapi.json post /v1/contract-pricing/rate-cards/create In Metronome, the rate card is the central location for your pricing. Rate cards were built with new product launches and pricing changes in mind - you can update your products and pricing in one place, and that change will be automatically propagated across your customer cohorts. Most clients need only maintain one or a few rate cards within Metronome. ### Use this endpoint to: - Create a rate card with a name and description - Define the rate card's single underlying fiat currency, and any number of conversion rates between that fiat currency and custom pricing units. You can then add products and associated rates in the fiat currency or custom pricing unit for which you have defined a conversion rate. - Set aliases for the rate card. Aliases are human-readable names that you can use in the place of the id of the rate card when provisioning a customer's contract. By using an alias, you can easily create a contract and provision a customer by choosing the paygo rate card, without storing the rate card id in your internal systems. This is helpful when launching a new rate card for paygo customers, you can update the alias for paygo to be scheduled to be assigned to the new rate card without updating your code. ### Key response fields: - The ID of the rate card you just created ### Usage guidelines: - After creating a rate card, you can now use the addRate or addRates endpoints to add products and their prices to it - A rate card alias can only be used by one rate card at a time. If you create a contract with a rate card alias that is already in use by another rate card, the original rate card's alias schedule will be updated. The alias will reference the rate card to which it was most recently assigned. # Get a rate card Source: https://docs.metronome.com/api-reference/rate-cards/get-a-rate-card /openapi.json post /v1/contract-pricing/rate-cards/get Return details for a specific rate card including name, description, and aliases. This endpoint does not return rates - use the dedicated getRates or getRateSchedule endpoints to understand the rates on a rate card. # Get a rate schedule Source: https://docs.metronome.com/api-reference/rate-cards/get-a-rate-schedule /openapi.json post /v1/contract-pricing/rate-cards/getRateSchedule A rate card defines the prices that you charge for your products. Rate cards support scheduled changes over time, to allow you to easily roll out pricing changes and new product launches across your customer base. Use this endpoint to understand the rate schedule `starting_at` a given date, optionally filtering the list of rates returned based on product id or pricing group values. For example, you may want to display a schedule of upcoming price changes for a given product in your product experience - use this endpoint to fetch that information from its source of truth in Metronome. If you want to understand the rates for a specific customer's contract, inclusive of contract-level overrides, use the `getContractRateSchedule` endpoint. # Get rates Source: https://docs.metronome.com/api-reference/rate-cards/get-rates /openapi.json post /v1/contract-pricing/rate-cards/getRates Understand the rate schedule at a given timestamp, optionally filtering the list of rates returned based on properties such as `product_id` and `pricing_group_values`. For example, you may want to display the current price for a given product in your product experience - use this endpoint to fetch that information from its source of truth in Metronome. If you want to understand the rates for a specific customer's contract, inclusive of contract-level overrides, use the `getContractRateSchedule` endpoint. # List rate cards Source: https://docs.metronome.com/api-reference/rate-cards/list-rate-cards /openapi.json post /v1/contract-pricing/rate-cards/list List all rate cards. Returns rate card IDs, names, descriptions, aliases, and other details. To view the rates associated with a given rate card, use the getRates or getRateSchedule endpoints. # Set the rate card products order Source: https://docs.metronome.com/api-reference/rate-cards/set-the-rate-card-products-order /openapi.json post /v1/contract-pricing/rate-cards/setRateCardProductsOrder The ordering of products on a rate card determines the order in which the products will appear on customers' invoices. Use this endpoint to set the order of products on the rate card. # Update a rate card Source: https://docs.metronome.com/api-reference/rate-cards/update-a-rate-card /openapi.json post /v1/contract-pricing/rate-cards/update Update a rate card's name, description, aliases, and credit type conversion rates. This endpoint does not affect underlying pricing rates or schedules. ### Use this endpoint to: - Rename rate cards: Update display names or descriptions for organizational clarity - Manage aliases: Add, modify, or schedule alias transitions for seamless and code-free rate card migrations - Update documentation: Keep rate card descriptions current with business context - Configure custom pricing units: Add credit type conversions to enable rates with different pricing units #### Active contract impact: - Alias changes: Already-created contracts continue using their originally assigned rate cards. - Other changes made using this endpoint will only impact the Metronome UI. #### Grandfathering existing PLG customer pricing: - Rate card aliases support scheduled transitions, enabling seamless rate card migrations for new customers, allowing existing customers to be grandfathered into their existing prices without code. Note that there are multiple mechanisms to support grandfathering in Metronome. #### How scheduled aliases work for PLG grandfathering: Initial setup: - Add alias to current rate card: Assign a stable alias (e.g., "standard-pricing") to your active rate card - Reference alias during contract creation: Configure your self-serve workflow to create contracts using `rate_card_alias` instead of direct `rate_card_id` - Automatic resolution: New contracts referencing the alias automatically resolve to the rate card associated with the alias at the point in time of provisioning #### Grandfathering process: - Create new rate card: Build your new rate card with updated pricing structure - Schedule alias transition: Add the same alias to the new rate card with a `starting_at` timestamp - Automatic cutover: Starting at the scheduled time, new contracts created in your PLG workflow using that alias will automatically reference the new rate card # Update the rate card products order Source: https://docs.metronome.com/api-reference/rate-cards/update-the-rate-card-products-order /openapi.json post /v1/contract-pricing/rate-cards/moveRateCardProducts The ordering of products on a rate card determines the order in which the products will appear on customers' invoices. Use this endpoint to set the order of specific products on the rate card by moving them relative to their current location. # Get audit logs Source: https://docs.metronome.com/api-reference/security/get-audit-logs /openapi.json get /v1/auditLogs Get a comprehensive audit trail of all operations performed in your Metronome account, whether initiated through the API, web interface, or automated processes. This endpoint provides detailed logs of who did what and when, enabling compliance reporting, security monitoring, and operational troubleshooting across all interaction channels. ### Use this endpoint to: - Monitor all account activity for security and compliance purposes - Track configuration changes regardless of source (API, UI, or system) - Investigate issues by reviewing historical operations ### Key response fields: An array of AuditLog objects containing: - id: Unique identifier for the audit log entry - timestamp: When the action occurred (RFC 3339 format) - actor: Information about who performed the action - request: Details including request ID, IP address, and user agent - `resource_type`: The type of resource affected (e.g., customer, contract, invoice) - `resource_id`: The specific resource identifier - `action`: The operation performed - `next_page`: Cursor for continuous log retrieval ### Usage guidelines: - Continuous retrieval: The next_page token enables uninterrupted log streaming—save it between requests to ensure no logs are missed - Empty responses: An empty data array means no new logs yet; continue polling with the same next_page token - Date filtering: - `starting_on`: Earliest logs to return (inclusive) - `ending_before`: Latest logs to return (exclusive) - Cannot be used with `next_page` - Resource filtering: Must specify both `resource_type` and `resource_id` together - Sort order: Default is `date_asc`; use `date_desc` for newest first # Get services Source: https://docs.metronome.com/api-reference/security/get-services /openapi.json get /v1/services Gets Metronome's service registry with associated IP addresses for security allowlisting and firewall configuration. Use this endpoint to maintain an up-to-date list of IPs that your systems should trust for Metronome communications. Returns service names and their current IP ranges, with new IPs typically appearing 30+ days before first use to ensure smooth allowlist updates. # Archive a pricing unit Source: https://docs.metronome.com/api-reference/settings/archive-a-pricing-unit /openapi.json post /v1/credit-types/archive Archive a custom pricing unit. Once archived, it will no longer appear in pricing unit selectors by default. # Create a pricing unit Source: https://docs.metronome.com/api-reference/settings/create-a-pricing-unit /openapi.json post /v1/credit-types/create Create a custom pricing unit. Custom pricing units can be used to charge for usage in a non-fiat pricing unit, for example AI credits. # List account-level billing providers Source: https://docs.metronome.com/api-reference/settings/list-account-level-billing-providers /openapi.json post /v1/listConfiguredBillingProviders Lists all configured billing providers and their delivery method configurations for your account. Returns provider details, delivery method IDs, and configuration settings needed for mapping individual customer contracts to billing integrations. # List pricing units Source: https://docs.metronome.com/api-reference/settings/list-pricing-units /openapi.json get /v1/credit-types/list List all pricing units. All fiat currency types (for example, USD or GBP) will be included, as well as any custom pricing units that were configured. Custom pricing units can be used to charge for usage in a non-fiat pricing unit, for example AI credits. Note: The USD (cents) pricing unit is 2714e483-4ff1-48e4-9e25-ac732e8f24f2. # Set up account-level billing provider Source: https://docs.metronome.com/api-reference/settings/set-up-account-level-billing-provider /openapi.json post /v1/setUpBillingProvider Set up account-level configuration for a billing provider. Once configured, individual contracts across customers can be mapped to this configuration using the returned delivery_method_id. # Upsert Anrok API token Source: https://docs.metronome.com/api-reference/settings/upsert-anrok-api-token /openapi.json post /v1/upsertAnrokApiToken Set the Anrok API token for some specified delivery_method_ids, which can be found in the `/listConfiguredBillingProviders` response. This maps the Anrok key to the appropriate billing entity. These API tokens are only used for Threshold Billing workflows today. # Upsert Avalara credentials Source: https://docs.metronome.com/api-reference/settings/upsert-avalara-credentials /openapi.json post /v1/upsertAvalaraCredentials Set the Avalara credentials for some specified `delivery_method_ids`, which can be found in the `/listConfiguredBillingProviders` response. This maps the Avalara credentials to the appropriate billing entity. These credentials are only used for PLG Invoicing today. # Get batched usage data Source: https://docs.metronome.com/api-reference/usage/get-batched-usage-data /openapi.json post /v1/usage Retrieve aggregated usage data across multiple customers and billable metrics in a single query. This batch endpoint enables you to fetch usage patterns at scale, broken down by time windows, making it ideal for building analytics dashboards, generating reports, and monitoring platform-wide usage trends. ### Use this endpoint to: - Generate platform-wide usage reports for internal teams - Monitor aggregate usage trends across your entire customer base - Create comparative usage analyses between customers or time periods - Support capacity planning with historical usage patterns ### Key response fields: An array of `UsageBatchAggregate` objects containing: - `customer_id`: The customer this usage belongs to - `billable_metric_id` and `billable_metric_name`: What was measured - `start_timestamp` and `end_timestamp`: Time window for this data point - `value`: Aggregated usage amount for the period - `groups` (optional): Usage broken down by group keys with values - `next_page`: Pagination cursor for large result sets ### Usage guidelines: - Time windows: Set `window_size` to `hour`, `day`, or `none` (entire period) - Required parameters: Must specify `starting_on`, `ending_before`, and `window_size` - Filtering options: - `customer_ids`: Limit to specific customers (omit for all customers) - `billable_metrics`: Limit to specific metrics (omit for all metrics) - Pagination: Use `next_page` cursor to retrieve large datasets - Null values: Group values may be null when no usage matches that group # Get usage data with paginated groupings Source: https://docs.metronome.com/api-reference/usage/get-usage-data-with-paginated-groupings /openapi.json post /v1/usage/groups Retrieve granular usage data for a specific customer and billable metric, with the ability to break down usage by custom grouping dimensions. This endpoint enables deep usage analytics by segmenting data across attributes like region, user, model type, or any custom dimension defined in your billable metrics. ### Use this endpoint to: - Analyze usage patterns broken down by specific attributes (region, user, department, etc.) - Build detailed usage dashboards with dimensional filtering - Identify high-usage segments for optimization opportunities ### Request parameters Use [`group_key`](#body-group-key) and [`group_filters`](#body-group-filters) to group by one or more dimensions. This is required for compound group keys and recommended for all new integrations: ```json { "group_key": ["region", "team"], "group_filters": { "region": ["US-East", "US-West"] } } ``` Important: For compound group keys, you must pass the complete set of keys that make up the compound key. Partial key combinations are not supported. For example, if your billable metric has a compound group key `[region, team, environment]`, you must pass all three keys in group_key—you cannot pass just `[region]` or `[region, team]`. ### Key response fields: An array of `PagedUsageAggregate` objects containing: - `starting_on` and `ending_before`: Time window boundaries - `group`: Object mapping group keys to their values - For simple groups, this will be a map with a single key-value pair (e.g., `{"region": "US-East"}`) - For compound groups, this will be a map with multiple key-value pairs (e.g., `{"region": "US-East", "team": "engineering"}`) - `value`: Aggregated usage for this group and time window - `next_page`: Pagination cursor for large datasets ### Usage guidelines: - Required parameters: Must specify `customer_id`, `billable_metric_id`, and `window_size` - Time windows: Set `window_size` to hour, day, or none for different granularities - Group filtering: Use `group_key` and `group_filters` to specify groups and group filters. Across all arrays in `group_filters`, include at most 200 filter values total. Requests with more than 200 filter values are rejected when this limit is enforced - Response limit: When using compound group keys (2+ keys in `group_key`), the default and maximum page size is 100 - Pagination: Use limit and `next_page` for large result sets - Null handling: Group values may be null for events missing the group key property # Ingest events Source: https://docs.metronome.com/api-reference/usage/ingest-events /openapi.json post /v1/ingest The ingest endpoint is the primary method for sending usage events to Metronome, serving as the foundation for all billing calculations in your usage-based pricing model. This high-throughput endpoint is designed for real-time streaming ingestion, supports backdating 34 days, and is built to handle mission-critical usage data with enterprise-grade reliability. Metronome supports 100,000 events per second without requiring pre-aggregation or rollups and can scale up from there. See the [Send usage events](/guides/events/send-usage-events) guide to learn more about usage events. ### Use this endpoint to: Create a customer usage pipeline into Metronome that drives billable metrics, credit drawdown, and invoicing. Track customer behavior, resource consumption, and feature usage ### What happens when you send events: - Events are validated and processed in real-time - Events are matched to customers using customer IDs or customer ingest aliases - Events are matched to billable metrics and are immediately available for usage and spend calculations ### Usage guidelines: - Historical events can be backdated up to 34 days and will immediately impact live customer spend - Duplicate events are automatically detected and ignored (34-day deduplication window) #### Event structure: Usage events are simple JSON objects designed for flexibility and ease of integration: ```json { "transaction_id": "2021-01-01T00:00:00Z_cluster42", "customer_id": "team@example.com", "event_type": "api_request", "timestamp": "2021-01-01T00:00:00Z", "properties": { "endpoint": "/v1/users", "method": "POST", "response_time_ms": 45, "region": "us-west-2" } } ``` Learn more about [usage event structure definitions](/guides/events/design-usage-events). #### Transaction ID The transaction_id serves as your idempotency key, ensuring events are processed exactly once. Metronome maintains a 34-day deduplication window - significantly longer than typical 12-hour windows - enabling robust backfill scenarios without duplicate billing. - Best Practices: - Use UUIDs for one-time events: uuid4() - For heartbeat events, use deterministic IDs - Include enough context to avoid collisions across different event sources #### Customer ID Identifies which customer should be billed for this usage. Supports two identification methods: - Metronome Customer ID: The UUID returned when creating a customer - Ingest Alias: Your system's identifier (email, account number, etc.) Ingest aliases enable seamless integration without requiring ID mapping, and customers can have multiple aliases for flexibility. #### Event Type: Categorizes the event type for billable metric matching. Choose descriptive names that aligns with the product surface area. #### Properties: Flexible metadata also used to match billable metrics or to be used to serve as group keys to create multiple pricing dimensions or breakdown costs by novel properties for end customers or internal finance teams measuring underlying COGs. # Search events Source: https://docs.metronome.com/api-reference/usage/search-events /openapi.json post /v1/events/search This endpoint retrieves events by transaction ID for events that occurred within the last 34 days. It is specifically designed for sampling-based testing workflows to detect revenue leakage. The Event Search API provides a critical observability tool that validates the integrity of your usage pipeline by allowing you to sample raw events and verify their matching against active billable metrics. Why event observability matters for revenue leakage: Silent revenue loss occurs when events are dropped, delayed, or fail to match billable metrics due to: - Upstream system failures - Event format changes - Misconfigured billable metrics ### Use this endpoint to: - Sample raw events and validate they match the expected billable metrics - Build custom leakage detection alerts to prevent silent revenue loss - Verify event processing accuracy during system changes or metric updates - Debug event matching issues in real-time ### Key response fields: - Complete event details including transaction ID, customer ID, and properties - Matched Metronome customer (if any) - Matched billable metric information (if any) - Processing status and duplicate detection flags ### Usage guidelines: ⚠️ Important: This endpoint is heavily rate limited and designed for sampling workflows only. Do not use this endpoint to check every event in your system. Instead, implement a sampling strategy to randomly validate a subset of events for observability purposes.