Skip to main content
Read metric data with the Public API (V2). Fetch a timeseries for graphs, an aggregated list for tables, or discover which metrics and tags a site has. All endpoints authenticate with your personal API token and are scoped to a single site_id.

Migrate from GraphQL metrics

Reading metrics through the GraphQL API is deprecated. If your integration reads metric data through GraphQL, use this comparison to move it to the REST API (V2) timeseries endpoint.

Query a timeseries

This endpoint returns one or more series of data points over a time range. Use it to draw graphs.

Request body

Each select entry requests one metric field. Provide a metric name, a tags object, and a field (see fields). Tag values may use * as a wildcard. You can also provide an aggregation (see aggregations) and a fill value. The fill values are ZERO (the default), PREVIOUS, and NONE. Existing integrations can also use the optional draw_null_as_zero field. If you send both fields, fill takes precedence. Use uppercase values for field and aggregation. The timeseries endpoint does not support group_by.

Response

Returns a Timeseries with the queried resolution, from, to, and a series array. Each series has an id, the metric name, its tags, the field it represents, min and max across the range, and a data array of points. Each point has a timestamp and a numeric value. Unlike the GraphQL metrics API, this endpoint does not require a separate metric keys request. Use the series array to see which tag and field combinations returned data. If a query may reach the processing limits, do not use series.length as the total number of matching metric keys.

Query a list

This endpoint returns aggregated metric values grouped into rows. Use it to build tables.

Request body

A ListSelector is like a timeseries selector, with an extra id that names the selector’s value in each row’s data object. group_by entries are Name (group by metric name) or Tag (group by a tag value). Use uppercase values for field and aggregation. The case-sensitive group_by values are Name and Tag. If a selector uses * for a tag in tags, add the same tag to group_by as {"Tag": "tag_name"} or the request fails.

Response

Returns a List with the queried resolution, from, to, and a rows array. Each row has an id, a group object of the tag values that define it, and a data object of aggregated values keyed by selector id (for example, { "mean": 42.5 }).

Page through a list

Add a pagination object to the request body to read the list in pages:
  • per_page: how many rows to return per page.
  • order: ASC or DESC. Rows are sorted by their id.
  • cursor: { "id": null } for the first page.
To get the next page, send the same request with cursor.id set to the last row’s id. Repeat until a page comes back with fewer rows than per_page. That page is the last one. A paginated response has the same shape as any other list response.
Pagination has limits. A request outside them returns a 400 response whose error field names the problem:
  • per_page accepts values from 1 to 1,000. Other values return pagination_invalid_per_page.
  • A paginated query reads up to 100,000 metric keys or rows across all its pages. Past that limit, it returns pagination_key_limit_exceeded instead of a partial result. Narrow the tag filters or the time range and send the request again.
  • For custom metrics, every tag that uses a * wildcard must also appear in group_by. The metric name cannot contain a wildcard. Otherwise the query returns pagination_requires_deterministic_grouping.
  • The event metrics event_duration and event_metric, and the incident error metric incident_error_count, cannot be paginated yet. They return pagination_unsupported_for_selector. Query them in a separate request without pagination.

List metric names

Return every metric name available for a site.
Returns an array of strings.

Get a metric’s type and tags

Return a metric’s type and the tag combinations it can be queried with.
Returns a metric_type (GAUGE, COUNTER, or MEASUREMENT) and available_tags, an array where each entry is one valid combination of tag keys.

Uptime monitor timings

The uptime_monitor_timing gauge records how long each phase of an uptime check took, in milliseconds. The phase tag selects the phase: dns, connect, tls, ttfb, download, or total. See request timing for what each phase measures. Query the metric with region, phase, and either the monitor name or id. phase behaves differently in the two query endpoints:
  • In a timeseries query, phase accepts the * wildcard and returns one series per phase.
  • In a list query, each selector must name one phase. Add one selector per phase you want, and group by region, name, or id, not by phase.
A phase the check did not measure is left out of the response. That applies to tls on a plain HTTP URL and to download without a body check. This list request returns the mean time per phase and region for one monitor:

High-cardinality metric queries

A metric query has high cardinality when it matches more series than the endpoint can process. AppSignal stores each unique tag combination as a separate metric key. For example, every combination of queue and worker values creates a separate metric key. The limits in this section apply to custom metrics and transaction_duration. They also apply to incident_error_count when a query uses a wildcard for incident_digest or revision. They do not apply to other metrics in the current V2 implementation. Each metric key and field combination counts as one series. For example, requesting MEAN and COUNT for one metric key counts as two series. For affected metrics, AppSignal limits how many series it processes before fetching their data:
  • /api/v2/metrics/timeseries processes up to 100 series.
  • /api/v2/metrics/list processes up to 1,000 series per page. A paginated query can read up to 100,000 metric keys across all its pages. See Page through a list.
These limits protect the metrics database from queries that would take too long to complete. They apply to the whole response, not separately to each select entry. The limit field cannot raise them. Dashboard charts load their data from /api/v2/metrics/timeseries, so the 100-series limit applies to charts too. If a query matches more series than the endpoint can process, AppSignal returns only part of the data. The response does not indicate that it is incomplete, so aggregated totals may be too low. Repeating the same query returns the same subset, but the result is still incomplete. To read more series from a list query, page through it. A paginated query that matches more than 100,000 metric keys returns pagination_key_limit_exceeded instead of a partial result. The Limits page shows which custom metrics report the most unique tag combinations per minute. When tag values change over time, a query over a longer range can match more series than the page shows. Custom metrics work best with tags that have a small, fixed set of values, such as region, plan, or queue. If an existing metric has high-cardinality tags, exact tag filters can reduce the number of matching series. However, the response cannot confirm that it contains every series. See Metric tags for guidance on choosing tag values.

Reference

Fields

The field selects which measurement to retrieve from a metric: For more type references, read the AppSignal V2 API Documentation.

Aggregations

The aggregation combines multiple values within a time bucket: SUM, AVERAGE, MIN, MAX, FIRST, or LAST.

Resolutions

resolution accepts MINUTELY, FIVE_MINUTELY, TEN_MINUTELY, FIFTEEN_MINUTELY, HOURLY, or DAILY.