get_node
const url = 'https://example.com/api/v1/nodes/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0';const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request GET \ --url https://example.com/api/v1/nodes/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0 \ --header 'Authorization: Bearer <token>'Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”Node id
Responses
Section titled “Responses”The node’s configuration, bindings and resolved kind
One node’s configuration detail, including its bindings (profile/credential/parent) so the node-detail page can show and edit them. Live mode only (PostgreSQL inventory).
object
The node’s address; 0.0.0.0 (or ::) means it has none (see NodeSummary.address).
DNS-monitor config when this node carries a dns_checks row; null otherwise.
object
Maximum CNAME hops before giving up (default 8).
The name to resolve, e.g. horryworks.net. Stored normalized (lowercase, no trailing dot).
Which record type the chain must reach (default A).
Recursive resolver to query. None ⇒ the poller container’s system resolver.
Resolver port (default 53).
Total budget for the whole chain walk, in milliseconds (default 3000).
The group this node belongs to; null ⇒ ungrouped.
Stable identifier for a monitored node.
A UUID, not a name or address — both of which can change over a node’s life.
The labels this node gets from its inventory folder and that folder’s ancestors, already minus the ones it excludes and minus anything it carries itself (ADR-135 inc. 2). Sorted.
Resolved on every read and never stored — a copy written onto the node row would go stale the moment a parent is edited or a folder is moved, which is the same call folder-pool and map-coordinate inheritance already made.
The screen draws tags and these as two marked groups; a chip here is removed by adding it
to tags_excluded, not by editing tags.
What this node is — the kind the scheduler actually polls it as, resolved by the one
precedence in [NodeKind::resolve].
The three configs below are the raw rows, and a node is not guaranteed to carry only one: the API edge refuses a second, but rows predating that guard exist. Reading the configs and concluding a kind from whichever is non-null is how the node page came to show a URL-monitor health card for a node the poller was treating as a Meraki device. Branch on this instead.
Cisco Meraki binding when this node carries a meraki_devices row; null otherwise.
object
Device model (e.g. “MX67”) — display only.
The Meraki networkId the device belongs to.
The Meraki organizationId (the API path segment) — denormalised for display.
Internal handle of the owning meraki_orgs row.
Meraki productType (appliance/switch/wireless/…).
The device serial — the join key returned by the org-bulk endpoints.
A Meraki MX’s warm-spare pair: its configured role, the other MX, and whether the site runs on
its spare (ADR-164 decision 26). null for a node that is not an MX in a pair.
object
The other MX; null when there is none, it cannot be told apart, or it sits in a folder the
caller cannot see — in which case state is unknown too.
This MX’s configured role.
What the pair is doing.
true when the Meraki device is a mesh repeater — an access point with no wired uplink,
whose address is therefore 0.0.0.0 (ADR-175). Absent otherwise.
The Meraki organization and network this node sits in, by name (ADR-185). null for a node
with no Meraki binding.
object
Meraki’s network id.
The network’s name as the last sync recorded it; null when no sync has named it yet.
Yagra’s id for the organization (the id of GET /api/v1/meraki/orgs), not Meraki’s.
The organization’s name as it was recorded when the organization was registered — a sync does not rewrite it.
The operator’s free-text note about this node; null ⇒ none (ADR-135).
⚠️ Detail only — deliberately not on NodeSummary. The inventory tree fetches one
summary per node and ADR-133 had just made that response smaller; a note is up to 2,000
characters that the tree does not draw.
The OS / software version the device last reported over SNMP (ADR-138), e.g. 15.0(2a)EX5;
null ⇒ never read — the node is not SNMP-polled, the version table does not cover the
device, or the poller that owns it predates the field.
⚠️ Observed, not configured. Nothing writes it but the poll path: the poller re-reads it
hourly, so it can trail an upgrade by up to an hour, and a poll that cannot read it leaves
the last value in place. Detail-only, like notes.
The node’s own poll-pool (ADR-009/020); null ⇒ it inherits from its folder, else the
default pool. Deliberately the raw stored value, not the effective one, so the edit form can
tell an explicit assignment from an inherited one — the effective pool (and which poller
currently holds the node) comes from GET /nodes/:id/assignment.
Whether a person fixed this node’s profile (ADR-140). A locked node is never offered on Nodes ▸ Reclassify; the edit dialog is where it is set and cleared. Detail-only.
The device’s serial number (ADR-147), e.g. FCW1929B68S; a stack lists every member in
order, joined with , . For an SNMP device it is the serial of each chassis in ENTITY-MIB,
read hourly; for a Meraki device it is the serial the node was imported with. null ⇒ not
known — the device keeps no chassis serial in ENTITY-MIB, or it has not been read yet.
⚠️ Observed, not configured, like os_version: it can trail a chassis swap by up to an
hour, and a read that fails leaves the last value in place. Detail-only.
Whether SNMP polling is configured for this node — not whether it is answering.
🚨 Do not re-derive this from credential_id. The scheduler falls back to the
deployment-wide YAGRA_SNMP_COMMUNITY for every node with no bound credential, so on such a
deployment a credential_id of null still means a device that is walked, has interface
rows and has neighbours. The WebUI uses this to hide the tabs whose only data source is an
SNMP walk (Interfaces, Neighbors — ADR-119); deriving it client-side would hide them on
exactly the nodes that have the data.
⚠️ Over-reports rather than under-reports — see
PollDispatcher::snmp_configured_for, which is the one place the rule lives.
The labels stored on this node (ADR-135). Empty when it has none, sorted.
Also detail-only, and for a second reason beyond size: the tree does not display them, and
NodeSummaryDto on the MCP side has carried them since before any writer existed.
⚠️ This is what the edit dialog writes back, so it is the node’s OWN set — not what it
effectively carries. The inherited half is inherited_tags below.
Labels this node refuses to inherit (ADR-135 inc. 2). Sorted.
Shown in full, including entries naming a label nothing currently supplies: an exclusion that cannot be seen cannot be undone, and it stays meaningful because an ancestor may re-add that label later.
URL-monitor config when this node carries a url_checks row; null otherwise.
object
How many bytes of the response body to read (default 65536, range 1024–1048576). Applies to
both body_match and json_extract; the body is not read at all unless one of them is set.
Follow 3xx redirects (default true).
Values to lift out of a JSON response body and record as operator-named metrics.
Each rule adds one gauge per poll. A rule whose path is missing, or whose value is not a number, records nothing for that poll rather than a zero.
One number to lift out of a JSON response body and record as a metric.
object
The metric name to record the value under, e.g. queue_depth. Must match
[A-Za-z_:][A-Za-z0-9_:]* and must not be one of the names the monitor already emits.
Dot-separated path to the value, e.g. data.queue.depth or items.0.value. Array elements
are indexed by number; items[0].value is accepted and means the same thing.
Not a JSONPath expression: the path names exactly one location, so the rule always produces either one number or nothing.
Request method (default GET).
Per-request timeout, in milliseconds (default 5000).
Full URL to probe, e.g. https://api.example.com/health.
Verify the TLS certificate chain (default true). Turning it off is an explicit operator
choice — it is never disabled silently.
Descriptive maker/model, editable from the node detail.
What this node is to the wireless inventory: a controller’s AP inventory and import settings,
or an imported access point’s entry in the AP list. null for a node that is neither.
object
Set when the node is an imported access point: its entry in the AP list. The controllers in it are limited to the ones the caller can see.
object
Stable id, derived from the MAC address. The same AP keeps it when the controller serving it changes.
Wireless clients online through this AP, as the serving controller reports it.
The node of the controller serving this AP: the last one to report it in service.
When a controller first reported this AP (RFC 3339).
Management address. null when the controller reports none, which it does for an AP that is
down.
When a controller last reported this AP in service (RFC 3339). null if it never has been.
When a controller last reported this AP (RFC 3339). It stops advancing when no controller reports the AP any more; the AP is never removed.
MAC address, lower-case and colon-separated.
Model, as the controller spells it.
The AP’s name on its controller.
The AP’s node, once it has been imported as one.
What each controller that reports this AP says, the serving controller first. Two entries for an AP behind an HA pair.
One controller’s view of one access point.
object
The reporting controller’s node.
When this controller last reported the AP in service (RFC 3339).
When this controller last reported the AP (RFC 3339).
The controller’s own word for the state (normal, fault, standby).
Software version.
The vendor’s own grouping of APs (a Huawei AP group).
Set when the node is a wireless controller that has reported an AP inventory or been given import settings.
object
The folder imported AP nodes are filed in. null ⇒ the folder this controller is in. No
folder is created for them.
How many access points the max_aps cap left out on the last import pass.
How many APs its last inventory carried.
Set when the controller reported more APs than one inventory may carry: how many it reported. The list then holds only the first ones by MAC address.
Whether access points this controller reports become nodes. On by default for a controller Yagra has just started reading; only APs that have been in service at least once are imported automatically.
When its last complete inventory arrived (RFC 3339). null if none has.
The most access points this controller imports (1–2048).
The controller’s node.
Example
{ "dns_check": { "record_type": "A" }, "kind": "wireless_ap", "meraki_pair": { "partner": { "node_state": "ok", "role": "primary" }, "role": "primary", "state": "normal" }, "url_check": { "body_match": { "mode": "contains" }, "expected_status": { "kind": "two_xx" }, "method": "GET" }, "wireless": { "ap": { "reported_by": [ { "state": "associated" } ], "state": "associated" }, "controller": { "flavor": "huawei" } }}No valid bearer token
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
object
Stable machine-readable code. Clients branch on this, never on the message.
Operator-facing sentence. Safe to display; never carries an internal error’s own text.
Examplegenerated
{ "error": { "code": "example", "message": "example" }}Role lacks the View permission
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
object
Stable machine-readable code. Clients branch on this, never on the message.
Operator-facing sentence. Safe to display; never carries an internal error’s own text.
Examplegenerated
{ "error": { "code": "example", "message": "example" }}No such node, or this deployment has no inventory
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
object
Stable machine-readable code. Clients branch on this, never on the message.
Operator-facing sentence. Safe to display; never carries an internal error’s own text.
Examplegenerated
{ "error": { "code": "example", "message": "example" }}