Skip to content

The node's adjacency change history, newest first.

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

A row is written only when the adjacency actually changed, so a quiet rack produces none. The content key deliberately excludes the agent’s own churn (LLDP’s TimeMark and remote index), so a row here means a port genuinely started or stopped facing something, or the peer on it changed.

node_id
required
string format: uuid

Node id

limit
integer format: int64
before_at
string
before_id
integer format: int64

One page of adjacency changes, newest first

Media typeapplication/json

One page of adjacency changes, newest first.

object
changes
required
Array<object>

One append-on-change history row.

object
at
required

When the change was recorded (RFC 3339).

string
id
required
integer format: int64
neighbors
required

The adjacency as of this change.

object
neighbors

The adjacencies, canonically ordered.

Array<object>

One observed adjacency.

The first three string fields are the identity; everything below them is payload. Payload changes still append a history row (a peer that was reimaged is a real change on that port), but they never split one link into two records.

object
capabilities

What the peer says it is, normalized across both protocols.

Array<string>
Allowed values: router bridge switch wlan_ap phone host repeater cable_device igmp other
local_ifindex

The local ifIndex, when the protocol genuinely supplies one. CDP indexes its cache by ifIndex so this is exact; LLDP’s lldpLocPortNum is an arbitrary local index that only often equals ifIndex, so LLDP records leave this None rather than guess.

integer | null format: int32
local_port
required

The local port, as the device names it: LLDP renders lldpLocPortId by its subtype, CDP uses cdpInterfaceName. Falls back to port <n> / ifindex <n> when the naming table has no row, so the record still has an identity rather than being dropped.

string
proto
required

Which protocol reported this.

string
Allowed values: lldp cdp
remote_chassis
required

The peer’s chassis id, rendered by subtype: LLDP lldpRemChassisId, CDP cdpCacheDeviceId.

string
remote_mgmt_addr

The peer’s management address, from cdpCacheAddress for CDP and from lldpRemManAddrTable for LLDP. None when the peer advertised none.

string | null
remote_platform

cdpCachePlatform — the peer’s hardware/software platform string (CDP only).

string | null
remote_port
required

The peer’s port id, rendered by subtype: LLDP lldpRemPortId, CDP cdpCacheDevicePort.

string
remote_port_desc

lldpRemPortDesc — the peer’s own description of its port.

string | null
remote_sys_desc

lldpRemSysDesc.

string | null
remote_sys_name

lldpRemSysName. CDP has no separate system name (its device id serves both).

string | null
truncated

Whether [MAX_NEIGHBORS_PER_NODE] was hit and rows were dropped. Reported rather than silently swallowed — a truncated view that looks complete is worse than no view.

boolean
prev_neighbor_key

The content key this replaced; null marks the first observation ever recorded for the node.

string | null
next
One of:
null
Example
{
"changes": [
{
"neighbors": {
"neighbors": [
{
"capabilities": [
"router"
],
"proto": "lldp"
}
]
}
}
]
}

Before_at and before_id must be given together, and before_at must be RFC 3339

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"
}
}

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 View

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"
}
}

Inventory storage is unavailable (skeleton mode)

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"
}
}