# Analyse and query meter usage Learn how to query and analyse meter usage data. Use the Meter Usage Analytics API to query and analyse your customers’ meter usage data. This enables you to build custom usage dashboards, generate reports, and determine consumption patterns across your meters. This API is available in public preview. to request access to this API. ## Query usage data The Meter Usage Analytics API returns aggregated usage data for a customer within a specified time interval. You can query for data by time periods, filter by meter dimensions, and query across multiple meters simultaneously. > The API parameters were updated in the 2025-09-30.preview release. See the [changelog](https://docs.stripe.com/changelog/clover/2025-09-30/update-meter-usage-fields.md) to understand how the request and response shapes changed. ### Fetch usage for a single meter Retrieve usage data for a specific customer and meter over a time range: ```curl curl -G https://api.stripe.com/v1/billing/analytics/meter_usage \ -u "<>:" \ -d starts_at=1735689600 \ -d ends_at=1738368000 \ -d customer={{CUSTOMER_ID}} \ -d "meters[0][meter]"={{METER_ID}} \ -d value_grouping_window=day \ --data-urlencode timezone="America/New_York" ``` ### Fetch usage for a meter filtered and grouped by meter dimension Query usage data that’s filtered by premium tier and grouped by model: ```curl curl -G https://api.stripe.com/v1/billing/analytics/meter_usage \ -u "<>:" \ -d starts_at=1735689600 \ -d ends_at=1738368000 \ -d customer={{CUSTOMER_ID}} \ -d "meters[0][meter]"={{METER_ID}} \ -d "meters[0][dimension_group_by_keys][0]"=model \ -d "meters[0][dimension_filters][tier]"=premium \ -d value_grouping_window=day ``` ### Fetch usage for a meter filtered by tenant Query usage data that’s filtered by premium tier and grouped by model: ```curl curl -G https://api.stripe.com/v1/billing/analytics/meter_usage \ -u "<>:" \ -d starts_at=1735689600 \ -d ends_at=1738368000 \ -d customer={{CUSTOMER_ID}} \ -d "meters[0][meter]"={{METER_ID}} \ -d "meters[0][tenant_filters][user_id]"=a8238bf39a1 \ -d value_grouping_window=day ``` ### Fetch usage across multiple meters Query usage across multiple meters with different filters and groupings: ```curl curl -G https://api.stripe.com/v1/billing/analytics/meter_usage \ -u "<>:" \ -d starts_at=1735689600 \ -d ends_at=1738368000 \ -d customer={{CUSTOMER_ID}} \ -d "meters[0][meter]"={{METER_ID_1}} \ -d "meters[0][dimension_group_by_keys][0]"=model \ -d "meters[0][dimension_group_by_keys][1]"=tier \ -d "meters[1][meter]"={{METER_ID_2}} \ -d "meters[1][dimension_filters][region]"=us-east \ -d value_grouping_window=day ``` ### Build usage dashboards You can use the API data to create visualisations, such as stacked charts that show usage across different dimensions. The following example demonstrates how you can structure data for a chart that shows API usage by model: ```curl curl -G https://api.stripe.com/v1/billing/analytics/meter_usage \ -u "<>:" \ -d starts_at=1735689600 \ -d ends_at=1738368000 \ -d customer={{CUSTOMER_ID}} \ -d "meters[0][meter]"={{METER_ID}} \ -d "meters[0][dimension_group_by_keys][0]"=model \ -d value_grouping_window=day ``` An example response to this request looks like: **View response** ```json { "data": [ { "starts_at": 1735689600, "ends_at": 1735776000, "value": 1500, "meter": "mtr_1234567890", "dimensions": { "model": "gpt-4" } }, { "starts_at": 1735689600, "ends_at": 1735776000, "value": 800, "meter": "mtr_1234567890", "dimensions": { "model": "gpt-3.5-turbo" } }, { "starts_at": 1735776000, "ends_at": 1735862400, "value": 2100, "meter": "mtr_1234567890", "dimensions": { "model": "gpt-4" } }, { "starts_at": 1735776000, "ends_at": 1735862400, "value": 950, "meter": "mtr_1234567890", "dimensions": { "model": "gpt-3.5-turbo" } } ] } ``` Use this example code to pull data from the API in your back end and display it to users as a stacked bar chart in your front end. **Your back end** ```javascript // Step 1: Extract the data from the Stripe API response const data = stripeApiResponse.data; // Step 2: Create a dictionary to store the processed data const processedData = {}; // Step 3: Iterate through the data and organize it by date and model data.forEach(point => { const date = new Date(point.bucket_start_time * 1000).toISOString().split('T')[0]; const model = point.dimensions.model; const value = point.bucket_value; if (!processedData[date]) { processedData[date] = {}; } processedData[date][model] = value; }); // Step 4: Create a list of unique models and sort them const models = [...new Set(data.map(point => point.dimensions.model))].sort(); // Step 5: Prepare the data for charting const chartData = []; Object.keys(processedData).sort().forEach(date => { const dataPoint = { date }; let cumulativeValue = 0; models.forEach(model => { const value = processedData[date][model] || 0; dataPoint[`${model}_start`] = cumulativeValue; cumulativeValue += value; dataPoint[`${model}_end`] = cumulativeValue; dataPoint[model] = value; // For simple stacked charts }); chartData.push(dataPoint); }); // Return chart data for front end chart library usage return chartData; ``` **Your front end** ```javascript // Step 1: Fetch usage chart data from your back end const chartData = await fetch('/api/customer_usage/:customer_id').then(r => r.json()); // Step 2: Extract unique models from the chart data const models = Object.keys(chartData[0]).filter(key => key !== 'date' && !key.endsWith('_start') && !key.endsWith('_end') ); // Step 3: Use the chart data to create your stacked bar chart // Example using D3 or Recharts: createStackedChart({ data: chartData.map(point => ({ date: point.date, 'gpt-4': point['gpt-4'] || 0, 'gpt-3.5-turbo': point['gpt-3.5-turbo'] || 0 })), stackKeys: models, xKey: 'date', title: 'Daily API Usage by Model' }); ``` ### Rate limits The Meter Usage Analytics API has its own rate limit of 100 requests per second per account, which is separate from the Stripe overall API rate limits. If you exceed this limit, the API returns a `429 Too Many Requests` status code. ### Event timestamp granularity The Meter Usage Analytics API truncates event timestamps to the nearest 15 minutes. For example, an event with `event_timestamp` of `08:42:15` is stored in our analytics database with a timestamp of `08:30:00`. ## Best practices ### Handle data freshness Usage data might have a slight delay. You can use the `data_refreshed_at` field in the response to understand data freshness. Also consider this latency when building real-time dashboards or alerts. ### Customise your queries Follow these best practices: - Use appropriate `value_grouping_window` values to balance granularity with performance. - Apply `dimension_filters` to reduce data volume when you only need specific segments. - Query multiple meters in a single request when analysing related usage patterns. ### Data size limits To prevent overly large responses, the following limits apply per meter: - A maximum of 5 `meters` - A maximum of 2 `dimension_group_by_keys` - A maximum of 10 `dimension_filters` - A maximum of 3 `tenant_filters` ### Handle errors The API returns standard HTTP status codes and structured error responses: ```json { "error": { "type": "invalid_request_error", "code": "invalid_time_range", "message": "Param start_time should not be greater than end_time" } } ```