Skip to content

L2TP#

Live L2TP tunnels — downstream (from LACs, terminated on this LNS) and upstream (to wholesale LNSes).

2 operations. Roles, error format and pagination are common to the whole API — see the REST API overview.

Authentication

Use a named bearer token. Every endpoint except POST /api/v1/auth/login, POST /api/v1/auth/enrol and GET /api/v1/system/health requires one. A super-user creates a token with POST /api/v1/auth/tokens; the plaintext (bngtok_…) is returned exactly once at creation and only a SHA-256 hash is stored on the appliance, so a lost token is replaced rather than recovered. Send it on every request:

Authorization: Bearer bngtok_…

Each token carries a fixed role (read-only, operator or super-user) and is exempt from CSRF checks. This is the single credential you need for scripts, integrations and monitoring.

Accounts and tokens share one identity model with the appliance CLI (login.users). Repeated authentication failures lock the account/source-IP pair out temporarily (HTTP 423 on login).

Session cookies (bundled web UI only)

The appliance also accepts an interactive session cookie, which is how the bundled web UI authenticates. It is documented for completeness — API clients should not use it. It is bound to a login session and obliges the caller to manage a CSRF token, neither of which suits automation.

POST /api/v1/auth/login with username + password (and a TOTP code when enrolled) sets the bng_session cookie and returns a csrfToken (also available from GET /api/v1/auth/whoami). Cookie-authenticated mutating requests (anything other than GET/HEAD/OPTIONS) must also send that value in the X-CSRF-Token header or they are rejected with 403.

NetavoBNG Management API v1#

Contact: Netavo

L2TP#


GET /api/v1/l2tp/tunnels#

List live L2TP tunnels (both directions).

Description

"downstream" tunnels arrive from LACs and terminate on this appliance (LNS role); "upstream" tunnels carry wholesale PPPoE subscribers to a remote LNS (LAC role). Rows are ordered downstream-first, then by local tunnel id. Fleet-proxyable.

Input parameters

Parameter In Type Default Nullable Description
bearerToken header string N/A No Named API token — the recommended credential for automation. See Authentication in the API overview.

Responses

{
    "tunnels": [
        {
            "direction": "downstream",
            "localTunnelId": 5,
            "peerTunnelId": 41027,
            "peerIp": "203.0.113.10",
            "peerHostname": "lac1.wholesale.example.net",
            "peerVendor": "Cisco Systems, Inc.",
            "state": "established",
            "sessions": 303
        }
    ]
}
Schema of the response body
{
    "required": [
        "tunnels"
    ],
    "type": "object",
    "properties": {
        "tunnels": {
            "type": "array",
            "items": {
                "$ref": "#/components/schemas/L2tpTunnel"
            },
            "description": "Live tunnels, downstream first, then by local tunnel id."
        }
    },
    "description": "GET /api/v1/l2tp/tunnels response.",
    "example": {
        "tunnels": [
            {
                "direction": "downstream",
                "localTunnelId": 5,
                "peerTunnelId": 41027,
                "peerIp": "203.0.113.10",
                "peerHostname": "lac1.wholesale.example.net",
                "peerVendor": "Cisco Systems, Inc.",
                "state": "established",
                "sessions": 303
            }
        ]
    }
}
{
    "type": "https://tools.ietf.org/html/rfc9110#section-15.5.5",
    "title": "VRF not found",
    "status": 404,
    "detail": "No VRF named 'wholesale-b' is configured.",
    "instance": "/api/v1/vrfs/wholesale-b"
}
Schema of the response body
{
    "type": "object",
    "properties": {
        "type": {
            "type": "string",
            "nullable": true
        },
        "title": {
            "type": "string",
            "nullable": true
        },
        "status": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "format": "int32",
            "nullable": true
        },
        "detail": {
            "type": "string",
            "nullable": true
        },
        "instance": {
            "type": "string",
            "nullable": true
        }
    },
    "example": {
        "type": "https://tools.ietf.org/html/rfc9110#section-15.5.5",
        "title": "VRF not found",
        "status": 404,
        "detail": "No VRF named 'wholesale-b' is configured.",
        "instance": "/api/v1/vrfs/wholesale-b"
    }
}
{
    "type": "https://tools.ietf.org/html/rfc9110#section-15.5.5",
    "title": "VRF not found",
    "status": 404,
    "detail": "No VRF named 'wholesale-b' is configured.",
    "instance": "/api/v1/vrfs/wholesale-b"
}
Schema of the response body
{
    "type": "object",
    "properties": {
        "type": {
            "type": "string",
            "nullable": true
        },
        "title": {
            "type": "string",
            "nullable": true
        },
        "status": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "format": "int32",
            "nullable": true
        },
        "detail": {
            "type": "string",
            "nullable": true
        },
        "instance": {
            "type": "string",
            "nullable": true
        }
    },
    "example": {
        "type": "https://tools.ietf.org/html/rfc9110#section-15.5.5",
        "title": "VRF not found",
        "status": 404,
        "detail": "No VRF named 'wholesale-b' is configured.",
        "instance": "/api/v1/vrfs/wholesale-b"
    }
}

GET /api/v1/l2tp/tunnels/{id}#

Full detail for one L2TP tunnel.

Description

Everything known about the tunnel — peer identity and vendor, endpoints, VRF, state, timestamps — plus the subscriber sessions carried in it. Fleet-proxyable.

Input parameters

Parameter In Type Default Nullable Description
bearerToken header string N/A No Named API token — the recommended credential for automation. See Authentication in the API overview.
id path integer No The tunnel's local tunnel id (from the tunnel list).

Responses

{
    "found": true,
    "direction": "downstream",
    "localTunnelId": 5,
    "peerTunnelId": 41027,
    "peerIp": "203.0.113.10",
    "peerPort": 1701,
    "peerHostname": "lac1.wholesale.example.net",
    "peerVendor": "Cisco Systems, Inc.",
    "localEndpoint": "45.84.200.69",
    "vrfName": "transit",
    "state": "established",
    "sessions": 2,
    "createdUtc": "2026-08-02T09:11:04Z",
    "uptimeSeconds": 90546.214773,
    "lastActivityUtc": "2026-08-03T10:23:59Z",
    "sessionList": [
        {
            "id": 40213,
            "username": "alice@example.net",
            "encap": "l2tp",
            "ipv4": "100.64.12.37",
            "ipv6": "2001:db8:64:12::1",
            "localSessionId": 118,
            "peerSessionId": 9,
            "uptimeSeconds": 86412.538912
        }
    ]
}
Schema of the response body
{
    "type": "object",
    "properties": {
        "found": {
            "type": "boolean",
            "description": "Always true on a 200 (unknown tunnels return 404)."
        },
        "direction": {
            "type": "string",
            "description": "\"downstream\" (from a LAC, terminated here) or \"upstream\" (to a wholesale LNS)."
        },
        "localTunnelId": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "description": "Tunnel id on this appliance.",
            "format": "int32"
        },
        "peerTunnelId": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "description": "Tunnel id on the peer.",
            "format": "int32"
        },
        "peerIp": {
            "type": "string",
            "description": "Peer tunnel endpoint IP, or null when unknown.",
            "nullable": true
        },
        "peerPort": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "description": "Peer UDP port, or null when unknown.",
            "format": "int32",
            "nullable": true
        },
        "peerHostname": {
            "type": "string",
            "description": "The peer's L2TP Host Name AVP, or null when unknown.",
            "nullable": true
        },
        "peerVendor": {
            "type": "string",
            "description": "The peer's Vendor Name AVP, or null when unknown.",
            "nullable": true
        },
        "localEndpoint": {
            "type": "string",
            "description": "Local tunnel endpoint IP on this appliance, or null when unknown.",
            "nullable": true
        },
        "vrfName": {
            "type": "string",
            "description": "Transport VRF the tunnel rides in, or null for the global table.",
            "nullable": true
        },
        "state": {
            "type": "string",
            "description": "Tunnel state: idle | wait-ctl | established | closed."
        },
        "sessions": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "description": "Subscriber sessions currently carried in the tunnel.",
            "format": "int32"
        },
        "createdUtc": {
            "type": "string",
            "description": "UTC time the tunnel was established.",
            "format": "date-time",
            "nullable": true
        },
        "uptimeSeconds": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$",
            "description": "How long the tunnel has been up, in seconds (from DateTime? L2tpTunnelDetailDto.CreatedUtc to now),\n    or null when the establishment time is unknown.",
            "format": "double",
            "nullable": true
        },
        "lastActivityUtc": {
            "type": "string",
            "description": "UTC time of the last session activity seen in the tunnel.",
            "format": "date-time",
            "nullable": true
        },
        "sessionList": {
            "type": "array",
            "items": {
                "$ref": "#/components/schemas/L2tpTunnelSession"
            },
            "description": "The subscriber sessions carried in the tunnel."
        }
    },
    "description": "GET /api/v1/l2tp/tunnels/{id} — full detail for one tunnel + its subscriber sessions.",
    "example": {
        "found": true,
        "direction": "downstream",
        "localTunnelId": 5,
        "peerTunnelId": 41027,
        "peerIp": "203.0.113.10",
        "peerPort": 1701,
        "peerHostname": "lac1.wholesale.example.net",
        "peerVendor": "Cisco Systems, Inc.",
        "localEndpoint": "45.84.200.69",
        "vrfName": "transit",
        "state": "established",
        "sessions": 2,
        "createdUtc": "2026-08-02T09:11:04Z",
        "uptimeSeconds": 90546.214773,
        "lastActivityUtc": "2026-08-03T10:23:59Z",
        "sessionList": [
            {
                "id": 40213,
                "username": "alice@example.net",
                "encap": "l2tp",
                "ipv4": "100.64.12.37",
                "ipv6": "2001:db8:64:12::1",
                "localSessionId": 118,
                "peerSessionId": 9,
                "uptimeSeconds": 86412.538912
            }
        ]
    }
}
{
    "type": "https://tools.ietf.org/html/rfc9110#section-15.5.5",
    "title": "VRF not found",
    "status": 404,
    "detail": "No VRF named 'wholesale-b' is configured.",
    "instance": "/api/v1/vrfs/wholesale-b"
}
Schema of the response body
{
    "type": "object",
    "properties": {
        "type": {
            "type": "string",
            "nullable": true
        },
        "title": {
            "type": "string",
            "nullable": true
        },
        "status": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "format": "int32",
            "nullable": true
        },
        "detail": {
            "type": "string",
            "nullable": true
        },
        "instance": {
            "type": "string",
            "nullable": true
        }
    },
    "example": {
        "type": "https://tools.ietf.org/html/rfc9110#section-15.5.5",
        "title": "VRF not found",
        "status": 404,
        "detail": "No VRF named 'wholesale-b' is configured.",
        "instance": "/api/v1/vrfs/wholesale-b"
    }
}
Schema of the response body

{
    "type": "https://tools.ietf.org/html/rfc9110#section-15.5.5",
    "title": "VRF not found",
    "status": 404,
    "detail": "No VRF named 'wholesale-b' is configured.",
    "instance": "/api/v1/vrfs/wholesale-b"
}
Schema of the response body
{
    "type": "object",
    "properties": {
        "type": {
            "type": "string",
            "nullable": true
        },
        "title": {
            "type": "string",
            "nullable": true
        },
        "status": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "format": "int32",
            "nullable": true
        },
        "detail": {
            "type": "string",
            "nullable": true
        },
        "instance": {
            "type": "string",
            "nullable": true
        }
    },
    "example": {
        "type": "https://tools.ietf.org/html/rfc9110#section-15.5.5",
        "title": "VRF not found",
        "status": 404,
        "detail": "No VRF named 'wholesale-b' is configured.",
        "instance": "/api/v1/vrfs/wholesale-b"
    }
}
{
    "type": "https://tools.ietf.org/html/rfc9110#section-15.5.5",
    "title": "VRF not found",
    "status": 404,
    "detail": "No VRF named 'wholesale-b' is configured.",
    "instance": "/api/v1/vrfs/wholesale-b"
}
Schema of the response body
{
    "type": "object",
    "properties": {
        "type": {
            "type": "string",
            "nullable": true
        },
        "title": {
            "type": "string",
            "nullable": true
        },
        "status": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "format": "int32",
            "nullable": true
        },
        "detail": {
            "type": "string",
            "nullable": true
        },
        "instance": {
            "type": "string",
            "nullable": true
        }
    },
    "example": {
        "type": "https://tools.ietf.org/html/rfc9110#section-15.5.5",
        "title": "VRF not found",
        "status": 404,
        "detail": "No VRF named 'wholesale-b' is configured.",
        "instance": "/api/v1/vrfs/wholesale-b"
    }
}

Schemas#

L2tpTunnel#

Name Type Description
direction string "downstream" (from a LAC, terminated here) or "upstream" (to a wholesale LNS).
localTunnelId Tunnel id on this appliance — the key for the detail endpoint.
peerHostname string | null The peer's L2TP Host Name AVP, or null when unknown.
peerIp string | null Peer tunnel endpoint IP, or null when unknown.
peerTunnelId Tunnel id on the peer.
peerVendor string | null The peer's Vendor Name AVP (RFC 2661 §4.4.3) — the LAC/LNS software/vendor string. Only the live manager captures it; null on session-derived rows unless in demo mode.
sessions Subscriber sessions currently carried in the tunnel.
state string Tunnel state: idle | wait-ctl | established | closed.

L2tpTunnelDetail#

Name Type Description
createdUtc string(date-time) | null UTC time the tunnel was established.
direction string "downstream" (from a LAC, terminated here) or "upstream" (to a wholesale LNS).
found boolean Always true on a 200 (unknown tunnels return 404).
lastActivityUtc string(date-time) | null UTC time of the last session activity seen in the tunnel.
localEndpoint string | null Local tunnel endpoint IP on this appliance, or null when unknown.
localTunnelId Tunnel id on this appliance.
peerHostname string | null The peer's L2TP Host Name AVP, or null when unknown.
peerIp string | null Peer tunnel endpoint IP, or null when unknown.
peerPort Peer UDP port, or null when unknown.
peerTunnelId Tunnel id on the peer.
peerVendor string | null The peer's Vendor Name AVP, or null when unknown.
sessionList Array<L2tpTunnelSession> The subscriber sessions carried in the tunnel.
sessions Subscriber sessions currently carried in the tunnel.
state string Tunnel state: idle | wait-ctl | established | closed.
uptimeSeconds How long the tunnel has been up, in seconds (from DateTime? L2tpTunnelDetailDto.CreatedUtc to now), or null when the establishment time is unknown.
vrfName string | null Transport VRF the tunnel rides in, or null for the global table.

L2tpTunnelList#

Name Type Description
tunnels Array<L2tpTunnel> Live tunnels, downstream first, then by local tunnel id.

L2tpTunnelSession#

Name Type Description
encap string | null Access encapsulation ("l2tp" downstream, "pppoe-lac" upstream).
id BNG session id (key into /api/v1/sessions/{id}).
ipv4 string | null Assigned IPv4 address, or null.
ipv6 string | null IPv6 WAN address, or null.
localSessionId L2TP session id on this appliance.
peerSessionId L2TP session id on the peer.
uptimeSeconds Seconds since the session was established.
username string | null Subscriber username, or null when unknown.

ProblemDetails#

Name Type Description
detail string | null
instance string | null
status
title string | null
type string | null

Security schemes#

Name Type Scheme Description
bearerToken http bearer Named API token — the recommended credential for automation. See Authentication in the API overview.
sessionCookie apiKey Interactive session cookie used by the bundled web UI. Not the integration path for API clients — use a bearer token. See Authentication in the API overview.

Tags#

Name Description
L2TP Live L2TP tunnels — downstream (from LACs, terminated on this LNS) and upstream (to wholesale LNSes).