Skip to content

The threshold rules that reach one port (ADR-076 decision 11).

GET
/api/v1/nodes/{node_id}/interfaces/{ifindex}/thresholds
curl --request GET \
--url https://example.com/api/v1/nodes/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/interfaces/1/thresholds \
--header 'Authorization: Bearer <token>'

A port is governed by rules at six scope levels, and the narrow ones are usually not where the interesting rule lives — a fleet-wide “any link over 90%” is a global rule, and a page that listed only the port’s own rules would show an empty list about a port that is alerting.

Rules come from PostgreSQL on every call rather than from the alert engine’s snapshot, which refreshes on the config generation: a rule saved a second ago is not in that snapshot, and the operator who just pressed Save is precisely the caller of this endpoint. The node’s own metadata (profile, tag values, folder chain) does come from the snapshot — it is what decides whether a broad rule reaches this node, and it does not change under the operator’s hand.

node_id
required
string format: uuid

Node id

ifindex
required
integer format: int32

SNMP ifIndex of the interface

Every rule that reaches this port, from any scope level, most specific first, each flagged with whether it is in force

Media typeapplication/json
Array<object>

One rule that reaches a port, and whether it is the one in force there.

object
in_force
required

Whether this rule sits at the winning scope level for its metric — the most specific level that reaches this port, and among folder-group rules only the nearest group in the chain (ADR-013 + ADR-075 decision 11).

Several rules can carry true for one metric at once: the engine merges rules at the winning level by keeping the more restrictive bound of each severity. So this means “this rule contributes to the effective bound”, not “this rule is the effective bound”.

boolean
rule
required

The stored rule, in the same shape the rules list serves.

object
critical_above

Value at/above which the node is Critical. None = no upper critical bound.

number | null format: double
critical_below

Value at/below which the node is Critical. None = no lower critical bound.

number | null format: double
dwell_samples
required

Hysteresis: consecutive samples the breach must hold before transitioning, to damp oscillation at the threshold. 0/1 = transition immediately.

integer format: int32
metric
required

Stable metric name this rule applies to (e.g. cpu_util).

string
warning_above

Value at/above which the node is Warning. None = no upper warning bound.

number | null format: double
warning_below

Value at/below which the node is Warning. None = no lower warning bound.

number | null format: double
critical

The primary side’s critical bound. See direction.

number | null format: double
direction
required

Which way this rule’s warning/critical face. Superseded by the four bounds on the rule itself, which describe both sides; on a rule bounding both, this names the primary side only and describes half of what the rule does.

string
Allowed values: above below
id
required
string format: uuid
row_match

Which rows of a vendor table this rule applies to, by the row’s name — I/O, or MPU Board *. Case-insensitive, and * matches any run of characters. Absent means every row, and every metric that has no rows. At the same scope, a rule with a pattern wins over one without for the rows it matches.

string | null
scope_ids
required

Every profile, folder group, node or port this rule applies to — scope_level says which of those they are. Empty for a global rule, which applies to every node.

Array<string>
scope_level
required

The scope a threshold is defined at, ordered least → most specific: Interface (one port) wins over Node, which wins over a folder group, which wins over Group, which wins over Profile, which wins over Global (every node).

string
Allowed values: global profile group group_id node interface
warning

The primary side’s warning bound. See direction.

number | null format: double
Example
[
{
"rule": {
"direction": "above",
"scope_level": "global"
}
}
]

No valid bearer token

Media typeapplication/json

The ADR-019 envelope every failure renders as. pub(crate) and schema-bearing so the OpenAPI document can name one error shape for every endpoint (ADR-035) instead of leaving 4xx/5xx bodies undescribed — a client that has to guess the failure shape ends up parsing the success shape and reading undefined.

object
error
required
object
code
required

Stable machine-readable code. Clients branch on this, never on the message.

string
message
required

Operator-facing sentence. Safe to display; never carries an internal error’s own text.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example"
}
}

Role lacks ManageConfig, or the node is outside the token’s group scope

Media typeapplication/json

The ADR-019 envelope every failure renders as. pub(crate) and schema-bearing so the OpenAPI document can name one error shape for every endpoint (ADR-035) instead of leaving 4xx/5xx bodies undescribed — a client that has to guess the failure shape ends up parsing the success shape and reading undefined.

object
error
required
object
code
required

Stable machine-readable code. Clients branch on this, never on the message.

string
message
required

Operator-facing sentence. Safe to display; never carries an internal error’s own text.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example"
}
}

Skeleton mode has no write side

Media typeapplication/json

The ADR-019 envelope every failure renders as. pub(crate) and schema-bearing so the OpenAPI document can name one error shape for every endpoint (ADR-035) instead of leaving 4xx/5xx bodies undescribed — a client that has to guess the failure shape ends up parsing the success shape and reading undefined.

object
error
required
object
code
required

Stable machine-readable code. Clients branch on this, never on the message.

string
message
required

Operator-facing sentence. Safe to display; never carries an internal error’s own text.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example"
}
}