List BGP routes

These existing reads are included in the 1.4.4 OpenAPI reference. Ordinary authenticated operator, engineer and admin credentials are supported. Restricted read-only API keys receive 403; documentation inclusion does not change access.

GET /api/v1/bgp/routes

Search BGP best paths (engine-computed) with prefix filtering and pagination.

Auth: all authenticated roles

Query params:

Param Type Description
as_id UUID Filter by autonomous system
prefix CIDR Exact prefix or search base (e.g. 10.0.0.0/8)
match string Match mode: empty (exact), "longest", "covered"
device_id UUID Filter by next-hop device (next_hop_device_id)
selecting_device_id UUID Filter by selecting device perspective (device_id -- which BMP target produced this best-path)
origin_as int Filter by origin AS number
next_hop IP Filter by next-hop address
community string Filter by community string (substring match)
af string Filter by address family: ipv4 or ipv6 (filters by family(prefix))
limit int Max results (default 50, max 10000)
offset int Pagination offset (default 0, capped at 100,000)
at RFC 3339 As-of-T: return best-paths from bgp_best_path_history at this time instead of the live table. Malformed → 400.

Note: Offset is capped at 100,000 to prevent full-table scans on large RIBs. Clients needing deeper pagination should narrow results with prefix/origin_as/next_hop filters.

Response: 200 OK

{
  "routes": [
    {
      "as_id": "uuid",
      "routing_domain_id": "uuid",
      "prefix": "203.0.113.0/24",
      "device_id": "uuid",
      "device_hostname": "rr1",
      "next_hop": "198.51.100.2",
      "next_hop_device_id": "uuid",
      "origin_as": 65099,
      "as_path": "65002 65099",
      "local_pref": 100,
      "med": 0,
      "communities": "65001:100 65001:200",
      "source_peer_id": "uuid",
      "igp_metric": 20,
      "source": "loc_rib",
      "ecmp_count": 1,
      "updated_at": "2026-03-18T12:00:00Z",
      "path_count": 3
    }
  ],
  "total": 850000,
  "unique_prefixes": 335,
  "limit": 50,
  "offset": 0
}

Note: path_count is the number of distinct received paths for this prefix across all peers (via LEFT JOIN LATERAL on bgp_rib_entry). Value is 0 when no RIB entries exist (e.g., rib_mode = 'loc_rib'). Used by the frontend to show an expand chevron on rows with multiple paths.

Note: source and ecmp_count are always present. source is "loc_rib" when the best path was reported directly from the router's Loc-RIB, or "inferred" when the engine ran its own RFC 4271 decision process over received paths; ecmp_count is the number of equal-cost paths the winner tied with. igp_metric (the IGP cost to the next hop) is omitempty — omitted when unknown. deciding_step (omitempty) names the RFC 4271 §9.1 step the selection resolved at against the strongest runner-up (only_path, eligibility, local_pref, as_path_len, origin, med, ebgp_over_ibgp, igp_cost, router_id, tie, undetermined — the selection-funnel vocabulary): a router_id/tie row is one where a router applying RFC 5004 prefer-oldest (IOS's default; ~12 % of a real DN42 table, measured) may install a different next hop — the UI badges these rows "tie-break". Absent on rows written before the column existed.

total counts best-path rows — one per selecting device × prefix (each BMP target independently runs its own RFC 4271 decision process), so a prefix known to six route reflectors contributes six rows (device_hostname identifies the selecting router). unique_prefixes counts distinct prefixes over the whole filtered set.

When at is supplied, rows come from the best-path history as-of-T; a notice string is added (and total is 0) when the window has no recorded routes.