Stripe | Financial Infrastructure to Grow Your Revenue

Stripe | Financial Infrastructure to Grow Your Revenue

4466 articles

Record usage for billing with the API


Record usage for billing with the API

Learn how to record usage using the Stripe API.

You must record usage in Stripe to make sure you bill your customers the correct amounts each billing period. To record usage, first configure your meter, and then send meter events that include the event name configured on the meter, customer ID, numerical value, and a timestamp (optional).

You can decide how often you record usage in Stripe, for example as it occurs or in batches. Stripe processes meter events asynchronously, so aggregated usage in meter event summaries and on upcoming invoices might not immediately reflect recently received meter events.

Create meter events

Create a Meter Event using the API.

Command Line

Select a language

cURL

Stripe CLI

Ruby

Python

PHP

Java

Node.js

Go

.NET

No results

Idempotency

Use idempotency keys to prevent reporting usage for each event more than one time because of latency or other issues. Every meter event corresponds to an identifier that you can specify in your request. If you don’t specify an identifier, we auto-generate one for you.

Event timestamps

Make sure the timestamp is within the past 35 calendar days and isn’t more than 5 minutes in the future. The 5-minute window is for clock drift between your server and Stripe systems.

Usage values

The numerical usage value in the payload accepts decimal values. Decimal values are also supported on invoices. If the overall cycle usage is negative, Stripe reports the invoice line item usage quantity as 0.

Dimension cardinality limits

Stripe limits how many unique combinations of configured dimension payload key-value pairs it accepts:

  • For each meter, Stripe accepts up to 10,000 unique combinations for each hour that Stripe receives meter events.
  • For each customer on a meter, Stripe accepts up to 100 unique combinations across all events.

Events for dimension combinations already counted toward the applicable limit continue to process. Events that introduce a new dimension combination after either limit is reached are invalid and appear in v1.billing.meter.error_report_triggered with the meter_event_dimension_count_too_high error code.

Rate limits

Calls to the Meter Event endpoint in live mode are subject to a separate rate limit, and don’t count against your account’s global rate limit. The Meter Event limit is 1000 calls per second per Stripe account. Meter Events are additionally limited to one concurrent call per customer per meter.

In a sandbox, calls to the Meter Events endpoint count toward your global rate limit. For Connect platforms, calls on a connected account to the Meter Events endpoint also count toward the basic limit.

Meter events also have dimension cardinality limits, which limit the number of unique dimension payload combinations that Stripe accepts. These limits are separate from API request rate limits.

If you anticipate exceeding these limits, you have two options:

  • Pre-aggregate your usage data before sending it to Stripe. For example, instead of sending a Event for each individual user action, you could accumulate usage across multiple actions and send a single aggregated event periodically. This reduces the number of API calls while still accurately reporting total usage.
  • Use the high-throughput ingestion method with meter event streams for significantly higher volumes.

Note

If you’re a Connect platform making requests on behalf of a connected account using the Stripe-Account header, you’re subject to regular Stripe rate limits, which is 100 operations per second.

You can monitor for 429 status codes and implement a retry mechanism with an exponential back-off schedule to manage request volume.

High-throughput ingestion with higher rate limits API v2

With the API v2, you can send up to 10,000 events per second to Stripe using meter event streams. This works in live mode only.

This endpoint uses stateless authentication sessions. First, create a Meter Event Session to receive an authentication token. Authentication tokens are only valid for 15 minutes, so you must create a new meter event session when your token expires.

Next, use the returned authentication token to create your high-throughput meter events with the Meter Event Stream.

Note

Because of the large volume of API requests, we don’t include meter event stream requests in the Workbench Logs tab.

You can monitor for 429 status codes and implement a retry mechanism with an exponential backoff schedule to manage request volume.

Select a language

Ruby

Python

PHP

Java

Node.js

.NET

Go

No results

require 'stripe'
require 'date'

class MeterEventManager
 attr_accessor :api_key
 attr_accessor :meter_event_session

 def initialize(api_key)
 @api_key = api_key
 @meter_event_session = nil

Handle meter event errors

Stripe asynchronously processes meter events. If we find an error, we create one of the following Events:

EventDescriptionPayload type
v1.billing.meter.error_report_triggeredThis event occurs when a meter has invalid usage events.thin
v1.billing.meter.no_meter_foundThis event occurs when usage events have missing or invalid meter IDs.thin

Warning

To create an event destination that subscribes to thin events, enable Workbench in your Developer settings.

Example payloads

The following is an example payload for a v1.billing.meter.error_report_triggered event.

{
 "id": "evt_test_65R2GpwDsnmpzihMjdT16R2GDhI4SQdXJGRbvn7JA8mPEm",
 "object": "v2.core.event",
 "created": "2024-08-28T20:54:12.051Z",
 "data": {
 "developer_message_summary": "There is 1 invalid event",
 "reason": {
 "error_count": 1,
 "error_types": [
 {

Error codes

The reason.error_types.code provides the error categorization that triggered the error. Possible error codes include:

  • meter _ event _ customer _ not _ found
  • meter _ event _ no _ customer _ defined
  • meter _ event _ dimension _ count _ too _ high
  • archived _ meter
  • timestamp _ too _ far _ in _ past
  • timestamp _ in _ future
  • meter _ event _ value _ not _ found
  • meter _ event _ invalid _ value
  • no _ meter (supported only for the v1. billing. meter. no _ meter _ found event type)

Listen to events

You can listen to events by setting up a webhook endpoint or another type of event destination.

  1. On the Webhooks tab in Workbench, click Create new destination. Alternatively, use this template to configure a new destination in Workbench with the two event types pre-selected.
  2. Click Show advanced options, then select the Thin payload style.
  3. Select v1.billing.meter.error_report_triggered and v1.billing.meter.no_meter_found from the list of events.
  4. Create a handler to process the event. Select a language Python Ruby PHP Java Node.js.NET No results import os from stripe import StripeClient from stripe.events import V1BillingMeterErrorReportTriggeredEvent from flask import Flask, request, jsonify app = Flask(__name__) api_key = os.environ.get('the related setting') webhook_secret = os.environ.get('the related setting')
  5. Test your handler by configuring a local listener with the Stripe CLI to send events to your local machine for testing before deploying the handler to production. Use the --forward-thin-to flag to specify which URL to forward the thin events to and the --thin-events flag to specify which thin events to forward. You can forward all thin events with an asterisk ( *), or a subset of thin events to your application. $ stripe listen --forward-thin-to localhost:4242/webhooks --thin-events "*"
  6. Trigger test events to your handler. Use the trigger function to run the following commands, which simulates the respective events in your account for testing. $ stripe trigger v1.billing.meter.error_report_triggered --api-key <your-secret-key> $ stripe trigger v1.billing.meter.no_meter_found --api-key <your-secret-key>
  7. If you process events with a webhook endpoint, verify the webhook signatures to secure your endpoint and validate all requests are from Stripe.
  8. Correct and resend invalid events for re-processing.

See also

Last verified 2026-09-24

Is this helpful?