Topology Events (Read)
List Events
GET /api/v1/events
GET /api/v1/events?area_id={areaID}
GET /api/v1/events?area_id={areaID}&type={eventType}&entity_type={entityType}&router_id={routerID}&from={from}&to={to}&limit={limit}&offset={offset}
Query the topology event log. Returns time-ordered events (newest first) matching the filter criteria. With no area_id, the result is deployment-wide, as used by the Activity panel.
Query parameters:
area_id (optional) — UUID of one area; omit for deployment-wide events
type (optional) — Filter by event type. Valid event types: device_added, device_removed, device_flags_changed, link_added, link_removed, link_state_changed, link_cost_changed, stub_added, stub_removed, stub_cost_changed, adjacency_up, adjacency_down, adjacency_change, lsa_maxage. Note: snapshot_processed and lsa_received are no longer generated; only actual topology-changing events are persisted.
entity_type (optional) — Filter by entity type ("device", "link", "stub_network", "adjacency", "lsa")
router_id (optional) — Filter by OSPF router ID (e.g., "10.0.0.2")
from (optional) — Start time filter, RFC3339 (e.g., "2026-02-16T00:00:00Z")
to (optional) — End time filter, RFC3339 (e.g., "2026-02-17T00:00:00Z")
limit (optional) — Maximum number of events to return (default: 100, max: 1000)
entity_id (optional) — Filter by entity UUID (link or device ID). Returns only events whose entity_id matches the given UUID. Useful for per-link or per-device timeline views.
include_related (optional) — When "true" and entity_type=device, also returns link events (state changes, cost changes, etc.) for all links where this device is an endpoint. Enables a unified device timeline showing both device-level and link-level events.
offset (optional) — Number of events to skip for pagination (default: 0)
Response: 200 OK
{
"events": [
{
"id": "uuid",
"event_time": "2026-02-16T14:23:46.456Z",
"area_id": "uuid",
"collector_id": "collector-nyc-dc1-01",
"event_type": "link_cost_changed",
"entity_type": "link",
"entity_id": "uuid",
"router_id": "10.0.0.2",
"detail": {
"router_a": "10.0.0.2",
"router_b": "10.0.0.3",
"old_cost": 10,
"new_cost": 100
},
"incident_id": "uuid",
"display_names": {
"10.0.0.2": "core-rtr-01.ams",
"10.0.0.3": "edge-rtr-02.ams"
}
}
],
"total": 42,
"limit": 100,
"offset": 0
}
Optional cursor pagination (from 1.4.4):
Use pagination=cursor to traverse recorded history without offset shifts:
GET /api/v1/events?pagination=cursor&area_id={areaID}&limit=100
GET /api/v1/events?pagination=cursor&area_id={areaID}&limit=100&cursor={next_cursor}
This mode returns pagination: "cursor", events, limit, has_more,
next_cursor and window_to. It does not return total or offset. The
last page has has_more: false and next_cursor: null. Event objects retain
all the ordinary fields and enrichment described above.
Keep the same filters, including the presence or absence of from and to,
on every page; limit may change. Copy next_cursor as an opaque URL-encoded
query value. Do not send offset, including offset=0, with this mode.
The first request fixes window_to to to, or the current server time if
omitted, at microsecond precision. Future to values and from > window_to
are rejected. Rows are ordered by event time and UUID, descending.
Cursors expire after 24 hours or an installation signing-key rotation. A
malformed, modified, expired or filter-mismatched cursor returns 400; start
a new traversal when it expires. Every page still requires authentication.
A cursor grants no access and does not extend history retention.
This is historical traversal, not a consistent database snapshot or lossless
incremental feed. Newer events do not shift the next page, but a later insert
with an older event time in an already traversed range can be missed. Retention
can remove rows between requests. Related-link membership, display names and
incident attribution reflect their state when each page is read.
Always check that the response says pagination: "cursor": release 1.4.3
ignores these unknown query parameters and returns the ordinary offset envelope.
Omitting pagination=cursor keeps the existing behavior used by the application.
Notes:
- Events are returned in descending order by
event_time (newest first).
- The
total field contains the total count of events matching the filter (before limit/offset), for pagination.
- The
entity_id field is omitted for events that do not map to a stored entity (e.g., adjacency_up, lsa_maxage).
- The
incident_id field contains the incident UUID when the event belongs to one; otherwise it is omitted.
- The
display_names field is an API-side enrichment (not stored in the database). It maps router IDs found in router_id, detail.router_id, detail.router_a, and detail.router_b to human-readable device names (hostname preferred, dns_name as fallback). Omitted when no names are available.
Error responses:
400 Bad Request — Invalid area UUID or RFC3339 timestamp; limit outside 1–1000; or a non-integer/negative offset
401 Unauthorized — Missing or invalid access token