Skip to main content
A metric alert is a PromQL threshold that notifies a channel when it crosses. It’s the alerting twin of a dashboard: the same slug identity, the same If-None-Match/If-Match ETag contract, the same 428/412 rules — only the collection name and body differ.

Reading alerts

Reads are always safe:
  • GET /v1/metric-alerts — summaries, with a cache-only collection ETag for If-None-Match.
  • GET /v1/metric-alerts/{slug} — one alert as a bare object, plus its resource ETag (an HTTP header) for conditional writes.

Writing alerts

An enabled alert pages people and fires webhooks. A server key can create, replace, and delete every alert in its project, and writes are not attributed. GET and keep the current body before any replace or delete, and don’t let an automation or agent mutate alerts unless that’s explicitly its job.

The document

The exact contract is MetricAlertInput in the OpenAPI spec; the essentials:
  • display_name — required, 1–255 characters. The slug is the immutable URL identity, never in the body.
  • severity — required; one of info, warning, critical.
  • enabled — required boolean, honored atomically: true starts evaluating immediately, and omitting the key is a 400, not a silent disable.
  • condition.expression — required PromQL: a top-level comparison of a vector query against one finite number literal (>, >=, <, <=), e.g. sum(rate(http_requests_total{"http.response.status_code"=~"5.."}[5m])) > 5. Every selector needs an exact metric name.
  • condition.recovery_expression — optional hysteresis: a second comparison pointing the opposite way whose band must not overlap the firing band (firing > 80, recovery < 70). Omitted → recovery is the negation of the firing expression.
  • notifications — required array of integration channel slugs (discover them via /v1/integrations). It’s a set — order doesn’t matter; a duplicate or unknown slug is 400; [] is valid (the alert fires but notifies nobody).
  • documentation.markdown — optional runbook (up to 16,384 bytes), delivered verbatim into every notification for this alert. Use inline links: [Runbook](https://…).
  • Unknown JSON fields are rejected with 400; the body is capped at 1 MiB; Content-Type: application/json is required.

Grouped alerts: one incident per series

The condition may return one series or many. A bare aggregate (sum(...)) is one series and fires one incident. A grouped query — sum by ("chain") (rate(m[5m])) > 5 — fires one independent incident per dimension value: chain="ethereum" can fire while chain="bsc" stays healthy, and the notification names the dimension that broke. Grouping is authored only inside the PromQL by (...) clause — there is no separate group-by field.

Sustained-ness: there is no for

Express duration inside the window function, and pick the function to match the intent: Firing and recovery may use different window functions as long as their numeric bands don’t overlap — e.g. firing min_over_time(m[5m]) > 600 with recovery max_over_time(m[5m]) < 60 gives a dead-band the signal must fully clear, so the alert can’t flap around a single threshold.

Execution semantics

Evaluation is event-driven, deliberately not Prometheus-compatible: each incoming datapoint for a watched metric re-evaluates the condition. A no-data, non-finite, or query-error evaluation holds the current state and never fires. Each returned series is its own incident keyed on its label set, opened and resolved independently.

Create

The conditional-write contract is identical to dashboards: create with If-None-Match: *, replace/delete with If-Match: "<etag>" from a fresh GET.

Notification channels

GET /v1/integrations and GET /v1/integrations/{slug} list the notification channels an alert can deliver to, as {slug, display_name, type, enabled}redacted: no webhook URL, headers, or routing keys are ever returned.
  • Channels are organization-scoped — the one collection that isn’t per-project. One slug is shared by every project in the org: an alert in project A and one in project B can both notify the channel named oncall.
  • This surface is read-only. Create and configure channels in the Mirador web app (see Integrations), then reference them by slug in an alert’s notifications.

Next Steps

Metrics

Discover the metrics your conditions evaluate

Automations

Trace-based rules and integrations in the web app