Metronome Usage API
[Usage events](https://docs.metronome.com/connecting-metronome/send-usage-data/) are the basis for billable metrics. Use these endpoints to send usage events to Metronome and retrieve aggregated event data.
[Usage events](https://docs.metronome.com/connecting-metronome/send-usage-data/) are the basis for billable metrics. Use these endpoints to send usage events to Metronome and retrieve aggregated event data.
openapi: 3.0.1
info:
title: Metronome Alerts Usage API
version: 1.0.0
description: '[Alerts](https://docs.metronome.com/connecting-metronome/alerts/) monitor customer spending, balances, and other billing factors. Use these endpoints to create, retrieve, and archive customer alerts. To view sample alert payloads by alert type, navigate [here.](https://docs.metronome.com/manage-product-access/create-manage-alerts/#webhook-notifications)'
servers:
- url: https://api.metronome.com
description: Production server
security:
- bearerAuth: []
tags:
- name: Usage
description: '[Usage events](https://docs.metronome.com/connecting-metronome/send-usage-data/) are the basis for billable metrics. Use these endpoints to send usage events to Metronome and retrieve aggregated event data.'
paths:
/v1/ingest:
post:
description: "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.\n\n### Use this endpoint to:\nCreate a customer usage pipeline into Metronome that drives billable metrics, credit drawdown, and invoicing. Track customer behavior, resource consumption, and feature usage\n\n### What happens when you send events:\n- Events are validated and processed in real-time\n- Events are matched to customers using customer IDs or customer ingest aliases\n- Events are matched to billable metrics and are immediately available for usage and spend calculations\n\n### Usage guidelines:\n- Historical events can be backdated up to 34 days and will immediately impact live customer spend\n- Duplicate events are automatically detected and ignored (34-day deduplication window)\n\n#### Event structure:\nUsage events are simple JSON objects designed for flexibility and ease of integration:\n```json\n{\n \"transaction_id\": \"2021-01-01T00:00:00Z_cluster42\",\n \"customer_id\": \"team@example.com\",\n \"event_type\": \"api_request\",\n \"timestamp\": \"2021-01-01T00:00:00Z\",\n \"properties\": {\n \"endpoint\": \"/v1/users\",\n \"method\": \"POST\",\n \"response_time_ms\": 45,\n \"region\": \"us-west-2\"\n }\n}\n```\n\nLearn more about [usage event structure definitions](/guides/events/design-usage-events).\n\n#### Transaction ID\n 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.\n - Best Practices:\n - Use UUIDs for one-time events: uuid4()\n - For heartbeat events, use deterministic IDs\n - Include enough context to avoid collisions across different event sources\n\n#### Customer ID\nIdentifies which customer should be billed for this usage. Supports two identification methods:\n - Metronome Customer ID: The UUID returned when creating a customer\n - Ingest Alias: Your system's identifier (email, account number, etc.) \n\nIngest aliases enable seamless integration without requiring ID mapping, and customers can have multiple aliases for flexibility.\n\n#### Event Type:\nCategorizes the event type for billable metric matching. Choose descriptive names that aligns with the product surface area.\n\n#### Properties:\nFlexible 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.\n"
operationId: ingest-v1
summary: Ingest events
x-nlb-domain-variable: ingestnlbDomain
x-vpc-connection-id-variable: ingestvpcLinkId
x-slo-tier: 1
tags:
- Usage
responses:
'200':
description: Success
requestBody:
content:
application/json:
schema:
type: array
minItems: 1
maxItems: 100
items:
$ref: '#/components/schemas/Event'
example:
- transaction_id: 2021-01-01T00:00:00Z_cluster42
customer_id: team@example.com
event_type: heartbeat
timestamp: '2021-01-01T00:00:00Z'
properties:
cluster_id: '42'
cpu_seconds: 60
region: Europe
/v1/usage/seats:
post:
x-mint:
groups:
- ff:seats
description: Fetch seats usage data for the specified customer, broken into intervals of the specified length.
operationId: getSeatsUsage-v1
summary: Get seats usage data
parameters:
- $ref: '#/components/parameters/PageLimit'
- $ref: '#/components/parameters/NextPage'
requestBody:
description: The seats query to run
content:
application/json:
schema:
$ref: '#/components/schemas/SeatsUsageQueryPayload'
example:
customer_id: 04ca7e72-4229-4a6e-ab11-9f7376fccbcb
seat_metric_id: 222796fd-d29c-429e-89b2-549fabda4ed6
starting_on: '2023-01-01T00:00:00Z'
ending_before: '2023-01-03T00:00:00Z'
window_size: day
usage_type: max
tags:
- Usage
responses:
'200':
description: Success
content:
application/json:
schema:
type: object
required:
- data
- next_page
properties:
data:
type: array
items:
$ref: '#/components/schemas/SeatsUsageAggregate'
next_page:
type: string
nullable: true
example:
data:
- starting_on: '2023-01-01T00:00:00Z'
ending_before: '2023-01-02T00:00:00Z'
value: 1234
- starting_on: '2023-01-02T00:00:00Z'
ending_before: '2023-01-03T00:00:00Z'
value: 567
next_page: null
/v1/usage/groups:
post:
description: "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.\n\n### Use this endpoint to:\n- Analyze usage patterns broken down by specific attributes (region, user, department, etc.)\n- Build detailed usage dashboards with dimensional filtering\n- Identify high-usage segments for optimization opportunities\n\n### Request parameters\nUse [`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:\n```json\n{\n \"group_key\": [\"region\", \"team\"],\n \"group_filters\": {\n \"region\": [\"US-East\", \"US-West\"]\n }\n}\n```\nImportant: 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]`.\n\n### Key response fields:\nAn array of `PagedUsageAggregate` objects containing:\n- `starting_on` and `ending_before`: Time window boundaries\n- `group`: Object mapping group keys to their values\n - For simple groups, this will be a map with a single key-value pair (e.g., `{\"region\": \"US-East\"}`)\n - For compound groups, this will be a map with multiple key-value pairs (e.g., `{\"region\": \"US-East\", \"team\": \"engineering\"}`)\n- `value`: Aggregated usage for this group and time window\n- `next_page`: Pagination cursor for large datasets\n\n### Usage guidelines:\n- Required parameters: Must specify `customer_id`, `billable_metric_id`, and `window_size`\n- Time windows: Set `window_size` to hour, day, or none for different granularities\n- Group filtering: Use `group_key` and `group_filters` to specify groups and group filters\n- Limits: When using compound group keys (2+ keys in `group_key`), the default and max limit is 100\n- Pagination: Use limit and `next_page` for large result sets\n- Null handling: Group values may be null for events missing the group key property\n"
operationId: getPagedUsage-v1
summary: Get usage data with paginated groupings
x-slo-tier: 1
parameters:
- $ref: '#/components/parameters/PageLimit'
- $ref: '#/components/parameters/NextPage'
requestBody:
description: The usage query to run
content:
application/json:
schema:
$ref: '#/components/schemas/PagedUsageQueryPayload'
examples:
using_simple_group_key:
summary: Simple (single key) group_key
value:
customer_id: 04ca7e72-4229-4a6e-ab11-9f7376fccbcb
billable_metric_id: 222796fd-d29c-429e-89b2-549fabda4ed6
starting_on: '2021-01-01T00:00:00Z'
ending_before: '2021-01-03T00:00:00Z'
window_size: day
group_key:
- region
group_filters:
region:
- us-east1
- us-west1
using_compound_group_key:
summary: Compound (multi-key) group_key with group_filters
value:
customer_id: 04ca7e72-4229-4a6e-ab11-9f7376fccbcb
billable_metric_id: 222796fd-d29c-429e-89b2-549fabda4ed6
starting_on: '2021-01-01T00:00:00Z'
ending_before: '2021-01-03T00:00:00Z'
window_size: day
group_key:
- region
- team
group_filters:
region:
- us-east1
- us-west1
team:
- ui
tags:
- Usage
responses:
'200':
description: Success
content:
application/json:
schema:
type: object
required:
- data
- next_page
properties:
data:
type: array
items:
$ref: '#/components/schemas/PagedUsageAggregate'
next_page:
type: string
nullable: true
examples:
using_simple_group_key:
summary: Response using single-key group_key
value:
data:
- starting_on: '2021-01-01T00:00:00Z'
ending_before: '2021-01-02T00:00:00Z'
group_key: region
group_value: us-east1
group:
region: us-east1
value: 1234
- starting_on: '2021-01-01T00:00:00Z'
ending_before: '2021-01-02T00:00:00Z'
group_key: region
group_value: us-west1
group:
region: us-west1
value: 567
next_page: null
using_compound_group_key:
summary: Response using compound group_key and group_filters
value:
data:
- starting_on: '2021-01-01T00:00:00Z'
ending_before: '2021-01-02T00:00:00Z'
group_key: null
group_value: null
group:
region: us-east1
team: ui
value: 1234
- starting_on: '2021-01-01T00:00:00Z'
ending_before: '2021-01-02T00:00:00Z'
group_key: null
group_value: null
group:
region: us-west1
team: ui
value: 890
next_page: null
/v1/usage:
post:
description: "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.\n\n### Use this endpoint to:\n- Generate platform-wide usage reports for internal teams\n- Monitor aggregate usage trends across your entire customer base\n- Create comparative usage analyses between customers or time periods\n- Support capacity planning with historical usage patterns\n\n### Key response fields:\nAn array of `UsageBatchAggregate` objects containing:\n\n- `customer_id`: The customer this usage belongs to\n- `billable_metric_id` and `billable_metric_name`: What was measured\n- `start_timestamp` and `end_timestamp`: Time window for this data point\n- `value`: Aggregated usage amount for the period\n- `groups` (optional): Usage broken down by group keys with values\n- `next_page`: Pagination cursor for large result sets\n\n### Usage guidelines:\n- Time windows: Set `window_size` to `hour`, `day`, or `none` (entire period)\n- Required parameters: Must specify `starting_on`, `ending_before`, and `window_size`\n- Filtering options:\n - `customer_ids`: Limit to specific customers (omit for all customers)\n - `billable_metrics`: Limit to specific metrics (omit for all metrics)\n- Pagination: Use `next_page` cursor to retrieve large datasets\n- Null values: Group values may be null when no usage matches that group\n"
operationId: getUsageBatch-v1
summary: Get batched usage data
parameters:
- $ref: '#/components/parameters/NextPage'
requestBody:
description: The usage query to run
content:
application/json:
schema:
$ref: '#/components/schemas/UsageBatchQueryPayload'
example:
window_size: day
starting_on: '2021-01-01T00:00:00Z'
ending_before: '2021-01-03T00:00:00Z'
tags:
- Usage
responses:
'200':
description: Success
content:
application/json:
schema:
type: object
required:
- data
- next_page
properties:
data:
type: array
items:
$ref: '#/components/schemas/UsageBatchAggregate'
next_page:
type: string
nullable: true
example:
data:
- customer_id: d7abd0cd-4ae9-4db7-8676-e986a4ebd8dc
billable_metric_id: 9570e4f3-d1da-4b95-ba81-bd40ee002727
billable_metric_name: CPU hours
start_timestamp: '2021-01-01T00:00:00Z'
end_timestamp: '2021-01-02T00:00:00Z'
value: 1234
- customer_id: d7abd0cd-4ae9-4db7-8676-e986a4ebd8dc
billable_metric_id: 9570e4f3-d1da-4b95-ba81-bd40ee002727
billable_metric_name: CPU hours
start_timestamp: '2021-01-02T00:00:00Z'
end_timestamp: '2021-01-03T00:00:00Z'
value: 1234
next_page: null
/v1/events/search:
post:
description: "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. \n\nWhy event observability matters for revenue leakage:\nSilent revenue loss occurs when events are dropped, delayed, or fail to match billable metrics due to:\n- Upstream system failures\n- Event format changes\n- Misconfigured billable metrics\n\n### Use this endpoint to:\n- Sample raw events and validate they match the expected billable metrics\n- Build custom leakage detection alerts to prevent silent revenue loss\n- Verify event processing accuracy during system changes or metric updates\n- Debug event matching issues in real-time\n\n### Key response fields:\n- Complete event details including transaction ID, customer ID, and properties\n- Matched Metronome customer (if any)\n- Matched billable metric information (if any)\n- Processing status and duplicate detection flags\n\n### Usage guidelines:\n⚠️ 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.\n"
operationId: searchEvents-v1
summary: Search events
tags:
- Usage
requestBody:
description: Search events request
content:
application/json:
schema:
type: object
required:
- transactionIds
properties:
transactionIds:
type: array
items:
type: string
description: The transaction IDs of the events to retrieve
example:
transactionIds:
- 2021-01-01T00:00:00Z_cluster42
responses:
'200':
description: Success
content:
application/json:
schema:
type: array
items:
type: object
required:
- id
- transaction_id
- customer_id
- event_type
- timestamp
properties:
id:
type: string
customer_id:
type: string
description: The ID of the customer in the ingest event body
event_type:
type: string
properties:
type: object
additionalProperties: true
timestamp:
type: string
format: date-time
transaction_id:
type: string
is_duplicate:
type: boolean
processed_at:
type: string
format: date-time
matched_customer:
type: object
description: The customer the event was matched to if a match was found
properties:
id:
type: string
format: uuid
name:
type: string
matched_billable_metrics:
type: array
items:
$ref: '#/components/schemas/BillableMetricForEventsSearch'
example:
- id: 123e4567-e89b-12d3-a456-426614174000
transaction_id: 2021-01-01T00:00:00Z_cluster42
customer_id: team@example.com
event_type: heartbeat
timestamp: '2021-01-01T00:00:00Z'
properties:
cluster_id: '42'
cpu_seconds: 60
region: Europe
processed_at: '2021-01-01T00:00:05Z'
is_duplicate: false
matched_customer:
id: 98765432-10fe-cba9-8765-432109876543
name: Acme Corp
matched_billable_metrics:
- id: 8deed800-1b7a-495d-a207-6c52bac54dc9
name: CPU Hours
/v1/customers/{customer_id}/purchasedSeats:
get:
x-mint:
groups:
- ff:seats
description: Returns the number of seats purchased for the current period.
operationId: getPurchasedSeats-v1
summary: Get purchased seats
parameters:
- $ref: '#/components/parameters/CustomerId'
tags:
- Usage
responses:
'200':
description: Success
content:
application/json:
schema:
type: object
required:
- data
properties:
data:
type: array
items:
type: object
required:
- charge_id
- seat_count
properties:
charge_id:
type: string
format: uuid
seat_count:
type: integer
'404':
$ref: '#/components/responses/NotFound'
components:
schemas:
PagedUsageQueryPayload:
required:
- billable_metric_id
- customer_id
- window_size
type: object
properties:
customer_id:
type: string
format: uuid
billable_metric_id:
type: string
format: uuid
window_size:
type: string
description: A window_size of "day" or "hour" will return the usage for the specified period segmented into daily or hourly aggregates. A window_size of "none" will return a single usage aggregate for the entirety of the specified period.
enum:
- hour
- day
- none
- HOUR
- DAY
- NONE
- Hour
- Day
- None
starting_on:
type: string
format: date-time
ending_before:
type: string
format: date-time
group_by:
type: object
description: Use group_key and group_filters instead. Use a single group key to group by. Compound group keys are not supported.
deprecated: true
required:
- key
properties:
key:
type: string
description: The name of the group_by key to use
values:
type: array
description: Values of the group_by key to return in the query. Omit this if you'd like all values for the key returned.
minItems: 1
items:
type: string
minLength: 1
group_key:
$ref: '#/components/schemas/GroupKey'
group_filters:
$ref: '#/components/schemas/GroupFilter'
current_period:
type: boolean
description: If true, will return the usage for the current billing period. Will return an error if the customer is currently uncontracted or starting_on and ending_before are specified when this is true.
PropertyFilter:
type: object
required:
- name
properties:
name:
type: string
description: The name of the event property.
exists:
type: boolean
description: Determines whether the property must exist in the event. If true, only events with this property will pass the filter. If false, only events without this property will pass the filter. If null or omitted, the existence of the property is optional.
in_values:
type: array
items:
type: string
description: Specifies the allowed values for the property to match an event. An event will pass the filter only if its property value is included in this list. If undefined, all property values will pass the filter. Must be non-empty if present.
not_in_values:
type: array
items:
type: string
description: Specifies the values that prevent an event from matching the filter. An event will not pass the filter if its property value is included in this list. If null or empty, all property values will pass the filter. Must be non-empty if present.
GroupKeysArray:
type: array
items:
type: array
items:
type: string
description: Property names that are used to group usage costs on an invoice. Each entry represents a set of properties used to slice events into distinct buckets.
AggregationTypeForEventsSearch:
type: string
enum:
- count
- Count
- COUNT
- latest
- Latest
- LATEST
- max
- Max
- MAX
- sum
- Sum
- SUM
- unique
- Unique
- UNIQUE
- custom_sql
description: Specifies the type of aggregation performed on matching events. Includes "custom_sql" for events search endpoint responses.
BillableMetricForEventsSearch:
allOf:
- $ref: '#/components/schemas/BillableMetricBase'
- type: object
properties:
aggregation_type:
$ref: '#/components/schemas/AggregationTypeForEventsSearch'
SeatsUsageQueryPayload:
required:
- seat_metric_id
- customer_id
- window_size
- usage_type
type: object
properties:
customer_id:
type: string
format: uuid
seat_metric_id:
type: string
format: uuid
usage_type:
type: string
description: The type of usage to return, max or latest value.
enum:
- max
- latest
- MAX
- LATEST
- Max
- Latest
window_size:
type: string
description: A window_size of "day" or "hour" will return the usage for the specified period segmented into daily or hourly aggregates. A window_size of "none" will return a single usage aggregate for the entirety of the specified period.
enum:
- hour
- day
- none
- HOUR
- DAY
- NONE
- Hour
- Day
- None
starting_on:
type: string
format: date-time
ending_before:
type: string
format: date-time
current_period:
type: boolean
description: If true, will return the usage for the current billing period. Will return an error if the customer is currently uncontracted or starting_on and ending_before are specified when this is true.
EventTypeFilter:
type: object
properties:
in_values:
type: array
items:
type: string
description: A list of event types that are explicitly included in the billable metric. If specified, only events of these types will match the billable metric. Must be non-empty if present.
not_in_values:
type: array
items:
type: string
description: A list of event types that are explicitly excluded from the billable metric. If specified, events of these types will not match the billable metric. Must be non-empty if present.
description: An optional filtering rule to match the 'event_type' property of an event.
GroupKey:
type: array
description: 'Group key to group usage by. Supports both simple (single key) and compound (multiple keys) group keys.
For simple group keys, provide a single key e.g. `["region"]`.
For compound group keys, provide multiple keys e.g. `["region", "team"]`.
For streaming metrics, the keys must be defined as a simple or compound group key on the billable metric.
For compound group keys, all keys must match an exact compound group key definition — partial matches are not allowed.
Cannot be used together with `group_by`.
'
items:
type: string
minLength: 1
minItems: 1
example:
- region
- team
Event:
required:
- customer_id
- event_type
- timestamp
- transaction_id
type: object
properties:
transaction_id:
type: string
minLength: 1
maxLength: 128
customer_id:
type: string
minLength: 1
event_type:
type: string
minLength: 1
timestamp:
type: string
description: RFC 3339 formatted
properties:
type: object
additionalProperties: true
PagedUsageAggregate:
required:
- starting_on
- ending_before
- group_key
- group_value
- value
type: object
properties:
starting_on:
type: string
format: date-time
ending_before:
type: string
format: date-time
group_key:
type: string
nullable: true
description: Use `group` instead. The group key for single-key grouping.
deprecated: true
group_value:
type: string
nullable: true
description: Use `group` instead. The group value for single-key grouping.
deprecated: true
group:
type: object
additionalProperties:
type: string
description: 'Map of group key to their value for this usage aggregate.
For simple group keys, this should be a single key e.g. `{"region": "US-East"}`
For compound group keys, this should contain the values of each group key that forms the compound e.g. `{"region": "US-East", "team": "engineering"}`
'
value:
type: number
nullable: true
AggregationKey:
type: string
description: A key that specifies which property of the event is used to aggregate data. This key must be one of the property filter names and is not applicable when the aggregation type is 'count'.
CustomField:
type: object
description: 'Custom fields to be added eg. { "key1": "value1", "key2": "value2" }'
additionalProperties:
type: string
Error:
required:
- message
type: object
properties:
message:
type: string
BillableMetricBase:
required:
- name
- id
type: object
properties:
group_by:
type: array
description: (DEPRECATED) use group_keys instead
items:
type: string
description: A list of keys that can be used to additionally segment the values of the billable metric when making usage queries
group_keys:
$ref: '#/components/schemas/GroupKeysArray'
name:
type: string
id:
type: string
format: uuid
aggregate:
type: string
description: (DEPRECATED) use aggregation_type instead
aggregate_keys:
type: array
description: (DEPRECATED) use aggregation_key instead
items:
type: string
filter:
type: object
description: (DEPRECATED) use property_filters & event_type_filter instead
additionalProperties: true
aggregation_key:
$ref: '#/components/schemas/AggregationKey'
event_type_filter:
$ref: '#/components/schemas/EventTypeFilter'
property_filters:
$ref: '#/components/schemas/PropertyFiltersArray'
custom_fields:
x-cf-entity: billable_metric
$ref: '#/components/schemas/CustomField'
sql:
type: string
description: The SQL query associated with the bi
# --- truncated at 32 KB (36 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/metronome/refs/heads/main/openapi/metronome-usage-api-openapi.yml