Skip to content
anecticoDocsDashboard
Browse documentation
Reference

Metrics REST API

Use the supported metric discovery, aggregation, histogram, forecast, and deletion endpoints.

On this page

Use the Metrics REST API for direct integrations that cannot use the Anectico CLI. Give read clients metrics:read; deletion requires metrics:delete. OTLP ingestion is separate and requires ingest:write at POST https://api.anectico.com/v1/metrics.

All resource calls below use this base URL and header:

https://app.anectico.com/api/v1
X-Anectico-API-Key: an_...

Project selection is endpoint-specific. Name discovery, aggregation, and histogram queries take project_id in the query string; forecasts take it in the JSON body; deletion derives its scope from the credential. Label discovery also takes project_id in the query string and applies the metric name and requested time window to both key and value discovery.

List metric names

curl --fail-with-body \
  -H "X-Anectico-API-Key: $ANECTICO_API_KEY" \
  "https://app.anectico.com/api/v1/metrics/names?project_id=$ANECTICO_PROJECT"

Optional start_time and end_time query parameters are RFC 3339 timestamps. The response is alphabetical and capped at 1,000 names:

{
  "metrics": [
    {"name": "checkout.duration_ms", "type": "histogram"},
    {"name": "checkout.queue_depth", "type": "gauge"}
  ],
  "total_count": 2,
  "retrieved_at": "2026-07-21T12:00:00Z"
}

Types are counter, gauge, histogram, or summary when the ingested data supplies one.

Discover labels

curl --fail-with-body \
  -H "X-Anectico-API-Key: $ANECTICO_API_KEY" \
  "https://app.anectico.com/api/v1/metrics/checkout.duration_ms/labels?project_id=$ANECTICO_PROJECT&start_time=2026-07-21T00:00:00Z&end_time=2026-07-21T12:00:00Z"

The response contains label keys found on the requested metric and available values for each key:

{
  "labels": [
    {"name": "service_name", "values": ["checkout-api", "checkout-worker"]},
    {"name": "environment", "values": ["production"]},
    {"name": "region", "values": ["eu-west", "us-east"]}
  ]
}

URL-encode a metric name when constructing the path programmatically. Label discovery accepts the same optional start_time and end_time query parameters and scopes both label keys and values to the requested project, metric, and time window. A project-bound credential remains pinned to its signed project.

A label named after a recorded-content convention is omitted with all of its values unless the credential holds agents:content:read and the project's current read policy permits that content. The same decision applies to custom-label filters and group_by: a denied classified dimension is refused before its values are queried, rather than returning series whose labels were silently emptied and could collapse together.

Aggregate a metric

POST /metrics/aggregate returns time-ordered scalar series. Put project_id in the query string, not the JSON body.

curl --fail-with-body \
  -X POST \
  -H "X-Anectico-API-Key: $ANECTICO_API_KEY" \
  -H "Content-Type: application/json" \
  "https://app.anectico.com/api/v1/metrics/aggregate?project_id=$ANECTICO_PROJECT" \
  --data '{
    "metric_name": "checkout.queue_depth",
    "aggregation": "max",
    "step": "5m",
    "time_range": {
      "start": "2026-07-21T10:00:00Z",
      "end": "2026-07-21T12:00:00Z"
    },
    "filters": [
      {"key": "region", "values": ["eu-west", "us-east"]}
    ],
    "group_by": ["service_name"],
    "environment": "production"
  }'
{
  "series": [
    {
      "labels": {"service_name": "checkout-api"},
      "points": [
        {"timestamp": "2026-07-21T10:00:00Z", "value": 12},
        {"timestamp": "2026-07-21T10:05:00Z", "value": 18}
      ]
    }
  ]
}

Supported fields:

Field Required Behavior
metric_name Yes Exact metric name
time_range.start, time_range.end No RFC 3339 closed time window; retention still applies
step No Bucket size; defaults to 1h
aggregation No Defaults to avg
service_name No Exact emitting-service filter
environment No Exact deployment-environment filter
filters No Up to two label dimensions
group_by No Up to two label dimensions

Aggregations are avg, sum, min, max, count, p50, p95, p99, stddev, and variance. Steps are 1s, 5s, 10s, 30s, 1m, 5m, 10m, 15m, 30m, 1h, 6h, 12h, 1d, and 7d.

Each filter requires one to 50 non-empty, distinct values. Values within one filter use OR; different filter dimensions use AND. Filter and group keys must begin with a letter or underscore and may then contain letters, digits, _, ., or -, up to 128 characters.

Queries are bounded to 50 grouped series and 500 points per series. Narrow the time range, increase step, or reduce grouping when the API rejects a larger query.

Query a native histogram

POST /metrics/histogram returns the preserved explicit-bucket distribution for an OTLP histogram. It does not accept aggregation or group-by.

curl --fail-with-body \
  -X POST \
  -H "X-Anectico-API-Key: $ANECTICO_API_KEY" \
  -H "Content-Type: application/json" \
  "https://app.anectico.com/api/v1/metrics/histogram?project_id=$ANECTICO_PROJECT" \
  --data '{
    "metric_name": "checkout.duration_ms",
    "step": "5m",
    "time_range": {
      "start": "2026-07-21T10:00:00Z",
      "end": "2026-07-21T12:00:00Z"
    },
    "environment": "production"
  }'
{
  "metric_name": "checkout.duration_ms",
  "step": "5m",
  "cells": [
    {
      "timestamp": "2026-07-21T10:00:00Z",
      "upper_bound": 100,
      "upper_bound_infinite": false,
      "count": "42"
    },
    {
      "timestamp": "2026-07-21T10:00:00Z",
      "upper_bound": 0,
      "upper_bound_infinite": true,
      "count": "3"
    }
  ]
}

The terminal +Inf bucket uses upper_bound_infinite: true; ignore its numeric upper_bound. Each count belongs to the range after the preceding bound through the cell's upper bound; it is not a cumulative count. Protobuf uint64 counts may be encoded as JSON strings. A non-histogram metric, or old histogram data without preserved buckets, returns no distribution cells.

Forecast a metric

POST /metrics/forecast calculates an expected band from an average-value history. Unlike the aggregate and histogram endpoints, project_id is a JSON field.

curl --fail-with-body \
  -X POST \
  -H "X-Anectico-API-Key: $ANECTICO_API_KEY" \
  -H "Content-Type: application/json" \
  "https://app.anectico.com/api/v1/metrics/forecast" \
  --data @- <<JSON
{
  "metric_name": "checkout.queue_depth",
  "interval": "5m",
  "horizon": 24,
  "sensitivity": 0,
  "environment": "production",
  "project_id": "$ANECTICO_PROJECT",
  "time_range": {
    "start": "2026-07-14T12:00:00Z",
    "end": "2026-07-21T12:00:00Z"
  }
}
JSON

horizon is the number of future buckets, defaults to 24, and cannot exceed 1,000. sensitivity is 0 for automatic band width or a value from 1 through 10. Without a time range, the service uses the last seven days of retained history. The response always explains whether the model could fit the history; forecast is populated only when status is FORECAST_FIT_STATUS_READY.

{
  "metric_name": "checkout.queue_depth",
  "interval": "5m",
  "horizon": 24,
  "history_points": 2016,
  "required_history_points": 576,
  "missing_buckets": 0,
  "status": "FORECAST_FIT_STATUS_READY",
  "status_reason": "Forecast fitted from regular history with a stable daily seasonal pattern.",
  "confidence": 0.91,
  "band_semantics": "additive_holt_winters_brutlag_seasonal_deviation",
  "forecast": [
    {
      "timestamp": "2026-07-21T12:05:00Z",
      "expected": 11.8,
      "lower": 6.1,
      "upper": 17.5
    }
  ]
}

The possible statuses are FORECAST_FIT_STATUS_READY, FORECAST_FIT_STATUS_INSUFFICIENT_HISTORY, FORECAST_FIT_STATUS_IRREGULAR_HISTORY, and FORECAST_FIT_STATUS_NONSEASONAL. status_reason is the stable human-readable explanation; required_history_points is the two-daily-season minimum for the selected interval. missing_buckets counts expected grid timestamps skipped by forward gaps. Duplicate and out-of-order observations also make history irregular but do not themselves increase that count.

confidence is a deterministic seasonal-fit score from 0 through 1, not probability or interval coverage. band_semantics identifies the additive Holt-Winters/Brutlag seasonal-deviation model used for a ready response. An unavailable status returns an empty forecast together with these explicit fields, so an empty array is never ambiguous. A forecast remains a statistical expectation, not a root-cause explanation or capacity guarantee. When every historical value is non-negative, the expected value and both bounds are floored at zero; an additive trend cannot produce an impossible negative count, rate, or latency in the returned cone.

Delete a metric

curl --fail-with-body \
  -X DELETE \
  -H "X-Anectico-API-Key: $ANECTICO_API_KEY" \
  "https://app.anectico.com/api/v1/metrics/anectico.verification.value?project_id=$ANECTICO_PROJECT"

Deletion removes every datapoint with that metric name in one project and cannot be undone through Anectico. project_id is required: an organization-level credential must name the project to delete from, and there is no way to delete a metric across every project in one call. A project-scoped key may omit project_id and stays confined to its own project; naming a different one is rejected. Prefer the CLI, which sends your active project and requires explicit confirmation:

anectico metrics delete anectico.verification.value --yes

Deletion is durable, not a filter. Once a metric is deleted, its datapoints stop appearing in metric queries, series, exemplars, dashboards and exports — and a late or retried copy sent by an SDK after the delete stays hidden too, rather than reappearing. Alert rules honour the same deletion, including anomaly rules: a deleted metric cannot raise an alert, and cannot contribute to the value an alert reports.

Deletion is metric-specific. Removing one metric name leaves your traces, logs, errors and other metrics untouched; delete those through their own controls.