Update Metric Alert Rule

PUT /v1/traffic/alerts/{uuid}

Replaces the user-mutable fields of an existing rule. Evaluator-owned state (status, last_value, last_evaluated_at, last_triggered_at) is preserved across the update — only the configuration is replaced.

Send the full rule body, not a partial patch. Use the response from Get Alert as the starting point and modify the fields you want to change.

Plan-gated: requires the metric_alerts entitlement (403 without it).

Path parameters

uuid string (uuid) Req
Alert rule UUID.

Request body

Same shape as Create. endpoint_uuid is re-resolved on every update; pass an empty string to clear an endpoint scope.

Each channel's secret (a webhook's signing key):

  • **** — the placeholder every read answers — keeps the secret saved on the rule: the saved channel of the same type and target, else the saved channel at the same position when it has the same type (its URL was edited). A **** with no saved secret behind it is refused with 400 on notify_channels (see Errors).
  • "", or no secret key, removes it.
  • Any other value replaces it.

Response (200 OK)

The updated rule. status and other evaluator fields reflect the worker's last cycle, not the update. A channel that has a secret answers "secret": "****".

Deprecated: until the sunset this response also carries the legacy integer id and *_id fields. Don't use them; read uuid and the *_uuid fields.

Errors

400 Bad Request
Validation failure or unresolvable endpoint_uuid.
400 masked secret
A channel's secret is **** but the rule has no saved secret for it (no saved channel of the same type and target with a secret, nor one of the same type at that position). Keyed to notify_channels: channel #N: "****" is the masked placeholder of a saved secret, not a secret: send the webhook's secret, or none.
401 Unauthorized
Missing auth.
403 Forbidden
Plan doesn't include metric_alerts.
404 Not Found
No rule with that UUID owned by the caller.
Request — raise threshold, add a channel, keep the webhook secret
curl -X PUT "https://api.ngris.com/v1/traffic/alerts/019c12ab-1cf9-7acd-9ca4-e05a5284d4d8" \ -H "X-API-KEY: <your_api_key>" \ -H "Content-Type: application/json" \ -d '{ "name": "5xx spike on api", "metric": "error_rate_pct", "operator": ">", "threshold": 2.0, "window_seconds": 300, "endpoint_uuid": "019bb1e4-e785-77d2-9966-c3cff31d0a0e", "cooldown_seconds": 600, "enabled": true, "notify_channels": [ {"type": "email", "target": "ops@acme.dev"}, {"type": "email", "target": "oncall@acme.dev"}, {"type": "webhook", "target": "https://hooks.acme.dev/ngris", "secret": "****"} ] }'
Response — 200 OK
{ "uuid": "019c12ab-1cf9-7acd-9ca4-e05a5284d4d8", "name": "5xx spike on api", "threshold": 2.0, "notify_channels": [ {"type": "email", "target": "ops@acme.dev"}, {"type": "email", "target": "oncall@acme.dev"}, {"type": "webhook", "target": "https://hooks.acme.dev/ngris", "secret": "****"} ], "status": "ok", "last_value": 0.04, "updated_at": "2026-05-21T13:00:00Z" }
Was this helpful?
Was this helpful?