> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dodopayments.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Usage-Based Billing Integration guide

> Learn how to set up meters and send usage events to enable accurate usage-based billing with Dodo Payments.

<CardGroup cols={2}>
  <Card title="API Reference - Events Ingestion" icon="code" href="/api-reference/usage-events/ingest-events">
    Access the complete API documentation for ingesting usage events and test event ingestion requests and responses interactively.
  </Card>

  <Card title="API Reference - Meters Creation" icon="code" href="/api-reference/meters/create-meter">
    Explore the full API documentation for creating meters and interactively test meter creation requests and responses.
  </Card>
</CardGroup>

## Creating a Meter

Meters define how your usage events are aggregated and measured for billing purposes.

Before creating a meter, plan your usage tracking strategy:

* Identify what usage events you want to track
* Determine how events should be aggregated (count, sum, etc.)
* Define any filtering requirements for specific use cases

### Step-by-Step Meter Creation

Follow this comprehensive guide to set up your usage meter:

<Steps>
  <Step title="Configure Basic Information">
    Set up the fundamental details for your meter.

    <ParamField path="Meter Name" type="string" required>
      Choose a clear, descriptive name that identifies what this meter tracks.

      Examples: "Tokens", "API Calls", "Storage Usage", "Compute Hours"
    </ParamField>

    <ParamField path="Description" type="string">
      Provide a detailed explanation of what this meter measures.

      Example: "Counts each POST /v1/orders request made by the customer"
    </ParamField>

    <ParamField path="Event Name" type="string" required>
      Specify the event identifier that will trigger this meter.

      Examples: "token", "api.call", "storage.usage", "compute.session"
    </ParamField>

    <Info>
      The event name must match exactly what you send in your usage events. Event names are case-sensitive.
    </Info>
  </Step>

  <Step title="Configure Aggregation Settings">
    Define how the meter calculates usage from your events.

    <ParamField path="Aggregation Type" type="string" required>
      Select how events should be aggregated:

      <Tabs>
        <Tab title="Count">
          Simply counts the number of events received.

          Use case: API calls, page views, file uploads

          Calculation: Total number of events
        </Tab>

        <Tab title="Sum">
          Adds up values from a specific property in your events.

          Use case: Data transfer, storage consumption, processing time

          Calculation: Sum of all property values
        </Tab>

        <Tab title="Max">
          Records the highest value of a specific property during the billing period.

          Use case: Peak concurrent users, maximum storage used, highest bandwidth

          Calculation: Maximum property value observed
        </Tab>

        <Tab title="Last">
          Uses the most recent value of a specific property.

          Use case: Current plan tier, latest configuration setting

          Calculation: Last recorded property value
        </Tab>
      </Tabs>
    </ParamField>

    <ParamField path="Over Property" type="string">
      The property name from event metadata to aggregate over.

      <Warning>
        This field is required when using Sum, Max, or Last aggregation types.
      </Warning>
    </ParamField>

    <ParamField path="Measurement Unit" type="string" required>
      Define the unit label for display purposes in reports and billing.

      Examples: "calls", "GB", "hours", "tokens"
    </ParamField>
  </Step>

  <Step title="Configure Event Filtering (Optional)">
    Set up criteria to control which events are included in the meter.

    <Info>
      Event filtering allows you to create sophisticated rules that determine which events contribute to your usage calculations. This is useful for excluding test events, filtering by user tiers, or focusing on specific actions.
    </Info>

    **Enable Event Filtering**

    Toggle **Enable Event Filtering** to activate conditional event processing.

    **Choose Filter Logic**

    Select how multiple conditions are evaluated:

    <Tabs>
      <Tab title="AND Logic">
        All conditions must be true for an event to be counted. Use this when you need events to meet multiple strict criteria simultaneously.

        **Example:** Count API calls where `user_tier = "premium"` AND `endpoint = "/api/v2/users"`
      </Tab>

      <Tab title="OR Logic">
        At least one condition must be true for an event to be counted. Use this when you want to include events that meet any of several criteria.

        **Example:** Count events where `method = "POST"` OR `method = "PUT"` OR `method = "DELETE"`
      </Tab>
    </Tabs>

    **Setting Up Filter Conditions**

    <Steps>
      <Step title="Add Condition">
        Click **Add condition** to create a new filter rule.
      </Step>

      <Step title="Configure Property Key">
        Specify the property name from your event metadata.
      </Step>

      <Step title="Select Comparator">
        Choose from available operators:

        * `equals` - Exact match
        * `not equals` - Exclusion filter
        * `greater than` - Numeric comparison
        * `greater than or equals` - Numeric comparison (inclusive)
        * `less than` - Numeric comparison
        * `less than or equals` - Numeric comparison (inclusive)
        * `contains` - String contains substring
        * `does not contain` - String exclusion filter
      </Step>

      <Step title="Set Comparison Value">
        Set the target value for comparison.
      </Step>

      <Step title="Add Groups">
        Use **Add Group** to create additional condition groups for complex logic.
      </Step>
    </Steps>

    <Warning>
      Filtered properties must be included in your event metadata for the conditions to work properly. Events missing required properties will be excluded from counting.
    </Warning>
  </Step>

  <Step title="Create Meter">
    Review your meter configuration and click on **Create Meter**.

    <Check>
      Your meter is now ready to receive and aggregate usage events.
    </Check>
  </Step>
</Steps>

## Linking Meter in a Product

Once you have created your meter, you need to link it to a product to enable usage-based billing. This process connects your meter's usage data to pricing rules for customer billing.

Linking meters to products establishes the connection between usage tracking and billing:

* Products define pricing rules and billing behavior
* Meters provide usage data for billing calculations
* Multiple meters can be linked to a single product for complex billing scenarios

### Product Configuration Process

Transform your usage data into billable charges by properly configuring your product settings:

<Steps>
  <Step title="Choose Usage-Based Billing Product Type">
    Navigate to your product creation or editing page and select **Usage-Based** as the product type.
  </Step>

  <Step title="Select Associated Meter">
    Click on **Associated Meter** to open the meter selection panel from the side.

    This panel allows you to configure which meters will track usage for this product.
  </Step>

  <Step title="Add Your Meter">
    In the meter selection panel:

    1. Click **Add Meters** to view available meters
    2. Select the meter you created from the dropdown list
    3. The selected meter will appear in your product configuration
  </Step>

  <Step title="Configure Price Per Unit">
    Set the pricing for each unit of usage tracked by your meter.

    <ParamField path="Price Per Unit" type="number" required>
      Define how much to charge for each unit measured by your meter.

      **Example**: Setting `$0.50` per unit means:

      * 1,000 units consumed = 1,000 × \$0.50 = 500.00 charged
      * 500 units consumed = 500 × \$0.50 = 250.00 charged
      * 100 units consumed = 100 × \$0.50 = 50.00 charged
    </ParamField>
  </Step>

  <Step title="Set Free Threshold (Optional)">
    Configure a free usage allowance before billing begins.

    <ParamField path="Free Threshold" type="number">
      Number of units customers can consume at no charge before paid usage calculation starts.

      **How it works**:

      * Free threshold: 100 units
      * Price per unit: \$0.50
      * Customer usage: 250 units
      * **Calculation**: (250 - 100) × $0.50 = **$75.00\*\* charged
    </ParamField>

    <Info>
      Free thresholds are ideal for freemium models, trial periods, or providing customers with a base allowance included in their plan.
    </Info>

    <Check>
      The free threshold applies to each billing cycle, giving customers fresh allowances monthly or according to your billing schedule.
    </Check>
  </Step>

  <Step title="Save Configuration">
    Review your meter and pricing configuration, then click **Save Changes** to finalize the setup.

    <Check>
      Your product is now configured for usage-based billing and will automatically charge customers based on their measured consumption.
    </Check>

    **What happens next**:

    * Usage events sent to your meter will be tracked and aggregated
    * Billing calculations will apply your pricing rules automatically
    * Customers will be charged based on actual consumption during each billing cycle
  </Step>
</Steps>

<Note>
  Remember that you can add up to 10 meters per product, enabling sophisticated usage tracking across multiple dimensions like API calls, storage, compute time, and custom metrics.
</Note>

## Sending Usage Events

Once your meter is configured, you can start sending usage events from your application to track customer usage.

### Event Structure

Each usage event must include these required fields:

<ParamField body="event_id" type="string" required>
  Unique identifier for this specific event. Must be unique across all events.
</ParamField>

<ParamField body="customer_id" type="string" required>
  The Dodo Payments customer ID this usage should be attributed to.
</ParamField>

<ParamField body="event_name" type="string" required>
  The event name that matches your meter configuration. Event names trigger the appropriate meter.
</ParamField>

<ParamField body="timestamp" type="string">
  ISO 8601 timestamp when the event occurred. Defaults to current time if not provided.
</ParamField>

<ParamField body="metadata" type="object">
  Additional properties for filtering and aggregation. Include any values referenced in your meter's "Over Property" or filtering conditions.
</ParamField>

### Usage Events API Examples

Send usage events to your configured meters using the Events API:

<CodeGroup>
  ```javascript Node.js theme={null}
  const response = await fetch('https://test.dodopayments.com/events/ingest', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.DODO_PAYMENTS_API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      events: [
        {
          event_id: "api_call_1234",
          customer_id: "cus_atXa1lklCRRzMicTqfiw2", 
          event_name: "api.call",
          timestamp: new Date().toISOString(),
          metadata: {
            endpoint: "/v1/orders",
            method: "POST",
            response_size: 1024
          }
        }
      ]
    })
  });
  ```

  ```python Python theme={null}
  import requests
  from datetime import datetime

  response = requests.post(
      'https://test.dodopayments.com/events/ingest',
      headers={
          'Authorization': f'Bearer {api_key}',
          'Content-Type': 'application/json'
      },
      json={
          'events': [
              {
                  'event_id': 'api_call_1234',
                  'customer_id': 'cus_atXa1lklCRRzMicTqfiw2',
                  'event_name': 'api.call',
                  'timestamp': datetime.now().isoformat(),
                  'metadata': {
                      'endpoint': '/v1/orders',
                      'method': 'POST',
                      'response_size': 1024
                  }
              }
          ]
      }
  )
  ```

  ```curl cURL theme={null}
  curl -X POST 'https://test.dodopayments.com/events/ingest' \
    -H 'Authorization: Bearer YOUR_API_KEY' \
    -H 'Content-Type: application/json' \
    -d '{
      "events": [
        {
          "event_id": "api_call_1234",
          "customer_id": "cus_atXa1lklCRRzMicTqfiw2",
          "event_name": "api.call", 
          "timestamp": "2024-01-15T10:30:00Z",
          "metadata": {
            "endpoint": "/v1/orders",
            "method": "POST",
            "response_size": 1024
          }
        }
      ]
    }'
  ```
</CodeGroup>

## Usage-Based Billing Analytics

Monitor and analyze your usage-based billing data with comprehensive analytics dashboard. Track customer consumption patterns, meter performance, and billing trends to optimize your pricing strategy and understand usage behaviors.

### Overview Analytics

The Overview tab provides a comprehensive view of your usage-based billing performance:

#### Activity Metrics

Track key usage statistics across different time periods:

<ParamField path="Current Month" type="metric">
  Shows usage activity for the current billing period, helping you understand monthly consumption patterns.
</ParamField>

<ParamField path="All Time" type="metric">
  Displays cumulative usage statistics since you started tracking, providing long-term growth insights.
</ParamField>

<Tip>
  Use the time period selector to compare usage across different months and identify seasonal trends or growth patterns.
</Tip>

#### Meter Quantities Chart

<Frame>
  <img src="https://mintcdn.com/dodopayments/16r81mgDWvSgYER7/images/guides/usage-based-billing/meter-quantities-chart.png?fit=max&auto=format&n=16r81mgDWvSgYER7&q=85&s=1a8a39547bd0259a53d4591d7928c8ea" alt="Meter quantities chart showing usage trends over time with purple gradient visualization" style={{ maxHeight: '500px', width: 'auto' }} width="1602" height="888" data-path="images/guides/usage-based-billing/meter-quantities-chart.png" />
</Frame>

The meter quantities chart visualizes usage trends over time with the following features:

* **Time-series visualization**: Track usage patterns across days, weeks, or months
* **Multiple meter support**: View data from different meters simultaneously
* **Trend analysis**: Identify usage spikes, patterns, and growth trajectories

<Info>
  The chart automatically scales based on your usage volume and selected time range, providing clear visibility into both small fluctuations and major usage changes.
</Info>

### Events Analytics

<Frame>
  <img src="https://mintcdn.com/dodopayments/16r81mgDWvSgYER7/images/guides/usage-based-billing/events-table.png?fit=max&auto=format&n=16r81mgDWvSgYER7&q=85&s=0af7aad1d5e9a379eee18edc40aac157" alt="Events table showing event names, IDs, and pagination controls for detailed event analysis" style={{ maxHeight: '500px', width: 'auto' }} width="1601" height="896" data-path="images/guides/usage-based-billing/events-table.png" />
</Frame>

The Events tab provides granular visibility into individual usage events:

#### Event Information Display

The events table provides a clear view of individual usage events with the following columns:

* **Event Name**: The specific action or trigger that generated the usage event
* **Event ID**: Unique identifier for each event instance
* **Customer ID**: The customer associated with the event
* **Timestamp**: When the event occurred

<Info>
  This view allows you to track and monitor individual usage events across your customer base, providing transparency into billing calculations and usage patterns.
</Info>

### Customer Analytics

The Customers tab provides a detailed table view of customer usage data with the following information:

#### Available Data Columns

<ParamField path="Customer Email" type="string">
  Email address of the customer for identification.
</ParamField>

<ParamField path="Subscription ID" type="string">
  Unique identifier for the customer's subscription.
</ParamField>

<ParamField path="Free Threshold" type="number">
  Number of free units included in the customer's plan before charges apply.
</ParamField>

<ParamField path="Price Per Unit" type="currency">
  The cost per unit for usage beyond the free threshold.
</ParamField>

<ParamField path="Last Event" type="timestamp">
  Timestamp of the customer's most recent usage event.
</ParamField>

<ParamField path="Total Price" type="currency">
  Total amount charged to the customer for usage-based billing.
</ParamField>

<ParamField path="Consumed Units" type="number">
  Total number of units the customer has consumed.
</ParamField>

<ParamField path="Chargeable Units" type="number">
  Number of units that exceed the free threshold and are being charged.
</ParamField>

#### Table Features

* **Column Filtering**: Use the "Edit Columns" feature to show/hide specific data columns
* **Real-time Updates**: Usage data reflects the most current consumption metrics

## Aggregation Examples

Here are practical examples of how different aggregation types work:

### Understanding Aggregation Types

Different aggregation types serve different billing scenarios. Choose the right type based on how you want to measure and charge for usage.

### Practical Implementation Examples

These examples demonstrate real-world applications of each aggregation type with sample events and expected results.

<AccordionGroup>
  <Accordion title="Count Aggregation - API Calls">
    Scenario: Track the total number of API requests

    Meter Configuration:

    * Event Name: `api.call`
    * Aggregation Type: Count
    * Measurement Unit: `calls`

    **Sample Events**:

    ```json theme={null}
    {
      "events": [
        {"event_id": "call_1", "customer_id": "cus_123", "event_name": "api.call"},
        {"event_id": "call_2", "customer_id": "cus_123", "event_name": "api.call"},
        {"event_id": "call_3", "customer_id": "cus_123", "event_name": "api.call"}
      ]
    }
    ```

    Result: 3 calls billed to customer
  </Accordion>

  <Accordion title="Sum Aggregation - Data Transfer">
    Scenario: Bill based on total bytes transferred

    Meter Configuration:

    * Event Name: `data.transfer`
    * Aggregation Type: Sum
    * Over Property: `bytes`
    * Measurement Unit: `GB`

    **Sample Events**:

    ```json theme={null}
    {
      "events": [
        {
          "event_id": "transfer_1",
          "customer_id": "cus_123", 
          "event_name": "data.transfer",
          "metadata": {"bytes": 1073741824}
        },
        {
          "event_id": "transfer_2",
          "customer_id": "cus_123",
          "event_name": "data.transfer", 
          "metadata": {"bytes": 536870912}
        }
      ]
    }
    ```

    Result: 1.5 GB total transfer billed to customer
  </Accordion>

  <Accordion title="Max Aggregation - Peak Concurrent Users">
    Scenario: Bill based on highest concurrent user count

    Meter Configuration:

    * Event Name: `concurrent.users`
    * Aggregation Type: Max
    * Over Property: `count`
    * Measurement Unit: `users`

    **Sample Events**:

    ```json theme={null}
    {
      "events": [
        {
          "event_id": "peak_1",
          "customer_id": "cus_123",
          "event_name": "concurrent.users", 
          "metadata": {"count": 15}
        },
        {
          "event_id": "peak_2",
          "customer_id": "cus_123",
          "event_name": "concurrent.users",
          "metadata": {"count": 23}
        },
        {
          "event_id": "peak_3",
          "customer_id": "cus_123",
          "event_name": "concurrent.users",
          "metadata": {"count": 18}
        }
      ]
    }
    ```

    Result: 23 peak concurrent users billed to customer
  </Accordion>
</AccordionGroup>

### Event Filtering Examples

<Tabs>
  <Tab title="Filter by API Endpoint">
    Only count API calls to specific endpoints:

    Filter Configuration:

    * Property: `endpoint`
    * Comparator: `equals`
    * Value: `/v1/orders`

    Sample Event:

    ```json theme={null}
    {
      "event_id": "call_1",
      "customer_id": "cus_123",
      "event_name": "api.call",
      "metadata": {
        "endpoint": "/v1/orders",
        "method": "POST"
      }
    }
    ```

    Result: Events matching the filter criteria would be counted. Events with different endpoints would be ignored.
  </Tab>

  <Tab title="Filter by Value Range">
    Only count large file uploads:

    Filter Configuration:

    * Property: `file_size`
    * Comparator: `greater_than`
    * Value: `1048576` (1MB in bytes)

    Sample Event:

    ```json theme={null}
    {
      "event_id": "upload_1",
      "customer_id": "cus_123", 
      "event_name": "file.upload",
      "metadata": {
        "file_size": 5242880,
        "file_type": "image"
      }
    }
    ```

    Result: Files larger than 1MB would be counted. Smaller files would be ignored.
  </Tab>

  <Tab title="Complex Multi-Condition Filters">
    Count premium API calls during business hours:

    Filter Configuration (using AND logic):

    * Property: `plan_type`, Comparator: `equals`, Value: `premium`
    * Property: `hour`, Comparator: `greater_than_or_equal`, Value: `9`
    * Property: `hour`, Comparator: `less_than`, Value: `17`

    Sample Event:

    ```json theme={null}
    {
      "event_id": "call_1",
      "customer_id": "cus_123",
      "event_name": "api.call",
      "metadata": {
        "plan_type": "premium",
        "hour": 14,
        "endpoint": "/v1/analytics"
      }
    }
    ```

    Result: Premium API calls during business hours (9 AM - 5 PM) would be counted.
  </Tab>
</Tabs>

## Troubleshooting

Resolve common issues with usage-based billing implementation and ensure accurate tracking and billing.

### Common Issues

Most usage-based billing problems fall into these categories:

* Event delivery and processing issues
* Meter configuration problems
* Data type and formatting errors
* Customer ID and authentication issues

### Debugging Steps

When troubleshooting usage-based billing:

1. Verify event delivery in the Events analytics tab
2. Check meter configuration matches your event structure
3. Validate customer IDs and API authentication
4. Review filtering conditions and aggregation settings

### Solutions and Fixes

<AccordionGroup>
  <Accordion title="Events not showing in meter">
    Common causes:

    * Event name doesn't exactly match meter configuration
    * Event filtering conditions are excluding your events
    * Customer ID doesn't exist in your Dodo Payments account
    * Event timestamp is outside the current billing period

    Solutions:

    * Verify event name spelling and case sensitivity
    * Review and test your filtering conditions
    * Confirm customer ID is valid and active
    * Check event timestamps are recent and properly formatted
  </Accordion>

  <Accordion title="Aggregation not working as expected">
    Common causes:

    * Over Property name doesn't match event metadata keys
    * Metadata values are wrong data type (string vs number)
    * Missing required metadata properties

    Solutions:

    * Ensure metadata keys exactly match your Over Property setting
    * Convert string numbers to actual numbers in your events
    * Include all required properties in every event
  </Accordion>

  <Accordion title="Filtering not working">
    Common causes:

    * Filter property names don't match event metadata
    * Wrong comparator for data type (string vs number)
    * Case sensitivity in string comparisons

    Solutions:

    * Double-check property names match exactly
    * Use appropriate comparators for your data types
    * Consider case sensitivity when filtering strings
  </Accordion>
</AccordionGroup>

## Related API Reference

<CardGroup cols={2}>
  <Card title="Create Meter" icon="gauge" href="/api-reference/meters/create-meter">
    API reference for creating and configuring usage meters for tracking customer consumption
  </Card>

  <Card title="Ingest Usage Events" icon="arrow-right" href="/api-reference/usage-events/ingest-events">
    API reference for sending usage events to your configured meters for billing calculations
  </Card>
</CardGroup>
