# Analytics API Programmatically access Stripe-defined metrics. The Analytics API gives you synchronous, programmatic access to Stripe-defined metrics such as monthly recurring revenue (MRR), annual recurring revenue (ARR), and usage revenue. Use it to build your own dashboards, query metrics from an AI agent, or integrate Stripe data into your internal tools. Stripe offers three programmatic data products. Choose the one that matches the type of data you need: - The **Analytics API (this product)**: Returns Stripe-defined metrics synchronously, as JSON. For example, choose this when you want a small set of prebuilt metrics on demand, to get metrics you can use in a live dashboard, or to expose metrics to an AI agent. - The [Reports API](https://docs.stripe.com/reports/api.md): Returns large, pre-built datasets asynchronously as CSV files. Choose this when you need a bulk export of raw transaction data on a schedule. - The [Query Runs API](https://docs.stripe.com/reports/query-runs.md): Runs freeform SQL against your raw Stripe data asynchronously and returns CSV files. Choose this when you need full SQL flexibility on top of your underlying data. ## Concepts ### Metrics A **metric** is a quantitative value computed by aggregating raw Stripe data—for example, MRR, ARR, or usage revenue. You can reference a metric by either its **ID** (for example, `metric_61Sud3n5oAGVCWiSr5`) or its **common name** (for example, `revenue.mrr`). Each metric has a separate ID for live mode and sandbox mode; the common name is the same in both modes. If you provide both `id` and `name`, they must refer to the same metric. Monetary metric values are returned in minor units (for example, cents for USD). Percentage metric values are returned in basis points (for example, 100 for 1%). The unit returned by each metric is listed in [Supported metrics](https://docs.stripe.com/data/analytics/supported-metrics.md). Metrics often have **dimensions**—categorical attributes such as `customer`, `product`, or `price`—that you can filter or group results by. ### Metric namespaces A **metric namespace** is a group of metrics that share the same dimensions. All metrics in a single `metric_query` request must belong to the same namespace. For example, the `revenue` namespace contains `revenue.mrr` and `revenue.arr`. You can filter both by `price`, `product`, `customer`, and `subscription`, and group them by additional dimensions including `price_name`, `product_name`, and `customer_email`. ### Time ranges and granularity Each `metric_query` returns a time series at the specified `granularity`. The supported granularities are `day`, `week`, `month`, and `year`. The maximum time range you can query depends on the granularity: - `day`: up to 92 days - `week`: up to 397 days - `month` and `year`: no fixed limit For granularities other than `day`, the API snaps `starts_at` and `ends_at` to the nearest bucket boundary, so any timestamp within a bucket produces the same result. For example, a monthly query with `starts_at=2026-01-15T00:00:00Z` returns buckets starting on the first of each month. Weeks are bucketed Sunday through Saturday. ### Sandboxes The Analytics API works in [sandboxes](https://docs.stripe.com/sandboxes.md). Use the sandbox ID for a metric (or its common name, which is the same in both modes) when querying from a sandbox. ### Metric versioning Metric versions are tied to [API versions](https://docs.stripe.com/upgrades.md). When a metric’s definition changes, the new version receives a new ID and the common name points to the new version. Previous versions remain accessible by their ID. ## Supported metrics See [Supported metrics](https://docs.stripe.com/data/analytics/supported-metrics.md) for the complete list of available metrics, their dimensions, the units in which results are returned, and which dimensions support grouping and filtering. ## Example Send a `POST` request to [`/v2/data/analytics/metric_query`](https://docs.stripe.com/api/v2/data/analytics/metric-query-results/create.md) to retrieve metric data. The request body is JSON; you must include the `Stripe-Version` header. ### Example request ```curl curl -X POST https://api.stripe.com/v2/data/analytics/metric_query \ -H "Authorization: Bearer <>" \ -H "Stripe-Version: 2026-04-22.preview" \ --json '{ "metrics": [ { "name": "revenue.mrr" } ], "starts_at": "2026-03-01T00:00:00Z", "ends_at": "2026-03-04T00:00:00Z", "granularity": "day", "currency": "usd", "filters": { "price": [ "price_HG4jxINMyHorkI", "price_HG4UtyJbuJIsVt" ] }, "group_by": [ "price" ] }' ``` ### Example response ```json { "id": "mqr_UQTLLvlABBZlw0", "object": "v2.data.analytics.metric_query_result", "livemode": true, "refreshed_at": "2026-03-04T02:34:15Z", "created": "2026-03-04T18:00:00Z", "next_page_url": null, "previous_page_url": null, "data": [ { "id": "mqdr_UQTLKfAhfsdatx", "timestamp": "2026-03-01T00:00:00Z", "dimensions": { "price": "price_HG4jxINMyHorkI" }, "results": [ { "metric": "metric_61Sud3n5oAGVCWiSr5", "name": "revenue.mrr", "currency": "usd", "value": 9000 } ] }, { "id": "mqdr_UQTLXYtgGM7TNp", "timestamp": "2026-03-01T00:00:00Z", "dimensions": { "price": "price_HG4UtyJbuJIsVt" }, "results": [ { "metric": "metric_61Sud3n5oAGVCWiSr5", "name": "revenue.mrr", "currency": "usd", "value": 12000 } ] }, { "id": "mqdr_UQTLcb70nAS3vR", "timestamp": "2026-03-02T00:00:00Z", "dimensions": { "price": "price_HG4jxINMyHorkI" }, "results": [ { "metric": "metric_61Sud3n5oAGVCWiSr5", "name": "revenue.mrr", "currency": "usd", "value": 9150 } ] } ] } ``` For the full request and response schemas, see the [`MetricQueryResult` API reference](https://docs.stripe.com/api/v2/data/analytics/metric-query-results/object.md). ## Use the Stripe MCP You can use the [Stripe Model Context Protocol (MCP) server](https://docs.stripe.com/mcp.md)’s `execute_analytics` tool to query analytics metrics from an AI agent or code editor. The MCP tool calls the [`POST /v2/data/analytics/metric_query`](https://docs.stripe.com/api/v2/data/analytics/metric-query-results/create.md) endpoint for you, so you can retrieve metrics by describing what you want in natural language rather than constructing API requests manually. > OAuth support isn’t available for the Analytics MCP tool. To authenticate, [use a restricted API key as a bearer token](https://docs.stripe.com/mcp.md?mcp-client=other). ## Use cases ### Build an internal MRR dashboard Query daily MRR for a few prices, grouped by price, to power an internal revenue dashboard. ```javascript const stripe = require('stripe')('sk_test_...', { apiVersion: '2026-04-22.preview', }); const response = await stripe.v2.data.analytics.metricQuery.create({ metrics: [{ name: 'revenue.mrr' }], starts_at: '2026-01-01T00:00:00Z', ends_at: '2026-01-31T00:00:00Z', granularity: 'day', currency: 'usd', filters: { price: ['price_HG4jxINMyHorkI', 'price_HG4UtyJbuJIsVt'], }, group_by: ['price'], }); response.data.forEach((row) => { const date = new Date(row.timestamp).toISOString().split('T')[0]; const priceId = row.dimensions.price; const mrrDollars = (row.results[0].value / 100).toFixed(2); const currency = row.results[0].currency.toUpperCase(); console.log(`${date} | ${priceId} | ${currency} ${mrrDollars}`); }); ``` ### Track multiple metrics in the same namespace Query MRR and ARR together to display recurring revenue trends in a single chart. Both metrics live in the `revenue` namespace, so you can request them in a single call. ```javascript const stripe = require('stripe')('sk_test_...', { apiVersion: '2026-04-22.preview', }); const response = await stripe.v2.data.analytics.metricQuery.create({ metrics: [ { name: 'revenue.mrr' }, { name: 'revenue.arr' }, ], starts_at: '2026-01-01T00:00:00Z', ends_at: '2026-01-31T00:00:00Z', granularity: 'month', currency: 'usd', }); response.data.forEach((row) => { const month = row.timestamp.slice(0, 7); row.results.forEach((result) => { const dollars = (result.value / 100).toFixed(2); console.log(`${month} | ${result.name}: ${dollars} ${result.currency}`); }); }); ``` ## Pagination and the `limit` parameter Stripe doesn’t support pagination. Instead, `next_page_url` and `previous_page_url` are always `null`. The `limit` parameter caps the number of rows returned but doesn’t trigger pagination. The API sorts results deterministically by `timestamp`, then by dimension values when `group_by` is specified, so a smaller `limit` returns the earliest rows in that order. ## Errors | Error code | HTTP status | Description | | ------------------------------------------------ | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `not_found` | 404 | The specified metric doesn’t exist, or the metric is only accessible in live mode (when queried in a sandbox). | | `metric_inaccessible` | 403 | You don’t have the required permissions to view this metric. | | `metric_invalid_parameter_use` | 400 | The metrics in a single request don’t share the same namespace, or you tried to group by or filter on a dimension that doesn’t exist on the metric, or a filter value isn’t valid for the specified dimension. | | `metric_invalid_parameter_value` | 400 | A parameter value isn’t valid—for example, an unsupported `granularity`, an unsupported `currency` or `timezone`, more than 1 `group_by` dimension, more than 2 filter dimensions, more than 10 values per filter, or a `limit` greater than 1,000. | | `metric_invalid_time_range` | 400 | The time range is invalid—for example, `starts_at` is after `ends_at`, either is in the future, or the range exceeds the maximum for the requested `granularity`. | | `metric_query_rate_limit_exceeded` | 429 | Too many metric queries per second. | | `metric_query_concurrency_limit_exceeded` | 429 | Too many concurrent metric queries. | | `metric_query_metric_rate_limit_exceeded` | 429 | Too many queries per second for this specific metric. | | `metric_query_metric_concurrency_limit_exceeded` | 429 | Too many concurrent queries for this specific metric. |