Address pools#
4 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:
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.
One endpoint refuses the cookie outright: GET /api/v1/metrics, the Prometheus scrape, accepts a
bearer token only, so that a scraper can never keep a login session alive.
NetavoBNG Management API v1#
Address pools#
GET /api/v1/address-pools#
List address pools with live utilisation on this appliance.
Description
One row per configured pool, with a row per subnet. used counts committed and offered
blocks (a DHCP OFFER or a PPP negotiation holds its block until it completes or its hold
lapses); quarantined blocks were declined by a DHCP client and return after an hour;
held blocks (IPv6 pools) are reserved for IPoE lines whose session has ended, for
protocols ipoe ipv6-reservation-hours, and count as used.
cgnTranslated is true for an IPv4 pool in a VRF bound to on-box CGN — its addresses are
private, never announced, and may be reused on every appliance. 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
[
{
"name": "res-v4",
"family": "ipv4",
"vrf": "internet",
"delegationLength": 32,
"description": "Residential IPv4",
"size": 2044,
"used": 1712,
"free": 332,
"utilisationPercent": 83.8,
"allocationFailures": 0,
"cgnTranslated": false,
"exclude": [
"100.70.0.1"
],
"subnets": [
{
"prefix": "100.70.0.0/22",
"announce": true,
"size": 1023,
"used": 1001,
"free": 22,
"offered": 3,
"quarantined": 0,
"gateway": "100.70.0.1",
"held": 0
},
{
"prefix": "100.70.4.0/22",
"announce": true,
"size": 1021,
"used": 711,
"free": 310,
"offered": 0,
"quarantined": 1,
"gateway": null,
"held": 0
}
],
"held": 0
}
]
{
"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/address-pools/reservations#
List the IPv6 blocks held for IPoE lines whose session has ended.
Description
One row per reserved block on this appliance (docs/design/53 §53.8): the pool, the
block, the pool owner it is held for (the line's access identity), the physical circuit it
was reserved on (port:svlan:cvlan, at most one per pool), and when it was made and lapses.
Ordered by pool, then prefix. 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. |
limit |
query | 100 | No | Page size (1-1000, default 100). | |
offset |
query | 0 | No | Rows to skip. | |
pool |
query | string | No | Only this pool's reservations. |
Responses
{
"total": 1,
"offset": 0,
"limit": 100,
"items": [
{
"pool": "residential-v6-pd",
"prefix": "2a0e:9f81:9010:100::/56",
"owner": "cid:4654545031353232333840",
"circuit": "0:200:141",
"reservedUtc": "2026-10-14T09:12:40Z",
"expiresUtc": "2026-10-15T09:12:40Z"
}
]
}
Schema of the response body
{
"required": [
"total",
"offset",
"limit",
"items"
],
"type": "object",
"properties": {
"total": {
"pattern": "^-?(?:0|[1-9]\\d*)$",
"description": "Reservations matching (before paging).",
"format": "int32"
},
"offset": {
"pattern": "^-?(?:0|[1-9]\\d*)$",
"description": "The offset this page was taken at.",
"format": "int32"
},
"limit": {
"pattern": "^-?(?:0|[1-9]\\d*)$",
"description": "The effective page size.",
"format": "int32"
},
"items": {
"type": "array",
"items": {
"$ref": "#/components/schemas/AddressPoolReservation"
},
"description": "The page."
}
},
"description": "A page of held IPv6 reservations.",
"example": {
"total": 1,
"offset": 0,
"limit": 100,
"items": [
{
"pool": "residential-v6-pd",
"prefix": "2a0e:9f81:9010:100::/56",
"owner": "cid:4654545031353232333840",
"circuit": "0:200:141",
"reservedUtc": "2026-10-14T09:12:40Z",
"expiresUtc": "2026-10-15T09:12:40Z"
}
]
}
}
{
"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"
}
}
POST /api/v1/address-pools/reservations/clear#
Release held IPv6 reservations.
Description
Returns the held blocks to their pool at once: those of one pool, narrowed to
one owner or one block prefix when given — or, with all, every reservation in every
pool. A line whose block is released gets a different one when it next connects. Audited
with the acting identity (ADDRESS_POOL_RESERVATIONS_CLEARED). Operator role or above;
acts on this appliance only.
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. |
Request body
{
"pool": "residential-v6-pd",
"owner": "cid:4654545031353232333840",
"prefix": null,
"all": false
}
Other accepted types: application/*+json, text/json
Schema of the request body
{
"type": "object",
"properties": {
"pool": {
"type": "string",
"description": "The pool whose reservations to release. Required unless `all`.",
"nullable": true
},
"owner": {
"type": "string",
"description": "Only the reservation held for this owner.",
"nullable": true
},
"prefix": {
"type": "string",
"description": "Only the reservation of this block.",
"nullable": true
},
"all": {
"type": "boolean",
"description": "Every reservation in every pool; give it alone.",
"default": false
}
},
"description": "POST /api/v1/address-pools/reservations/clear body.",
"example": {
"pool": "residential-v6-pd",
"owner": "cid:4654545031353232333840",
"prefix": null,
"all": false
}
}
Responses
{
"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"
}
}
{
"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/address-pools/{name}/allocations#
List the sessions holding blocks from one address pool.
Description
Ordered by prefix. static marks a statically-assigned address that falls inside the pool
(held so the allocator never hands it out, but not disconnected if its subnet is removed).
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. |
limit |
query | 100 | No | Page size (1-1000, default 100). | |
name |
path | string | No | Pool name. | |
offset |
query | 0 | No | Rows to skip. |
Responses
{
"total": 1712,
"offset": 0,
"limit": 100,
"items": [
{
"prefix": "100.70.1.17/32",
"kind": "ipv4",
"sessionId": 40213,
"username": "alice@example.net",
"vrf": "internet",
"static": false
}
]
}
Schema of the response body
{
"required": [
"total",
"offset",
"limit",
"items"
],
"type": "object",
"properties": {
"total": {
"pattern": "^-?(?:0|[1-9]\\d*)$",
"description": "Allocations in the pool (before paging).",
"format": "int32"
},
"offset": {
"pattern": "^-?(?:0|[1-9]\\d*)$",
"description": "The offset this page was taken at.",
"format": "int32"
},
"limit": {
"pattern": "^-?(?:0|[1-9]\\d*)$",
"description": "The effective page size.",
"format": "int32"
},
"items": {
"type": "array",
"items": {
"$ref": "#/components/schemas/AddressPoolAllocation"
},
"description": "The page."
}
},
"description": "A page of an address pool's allocations.",
"example": {
"total": 1712,
"offset": 0,
"limit": 100,
"items": [
{
"prefix": "100.70.1.17/32",
"kind": "ipv4",
"sessionId": 40213,
"username": "alice@example.net",
"vrf": "internet",
"static": false
}
]
}
}
{
"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"
}
}
{
"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#
AddressPool#
| Name | Type | Description |
|---|---|---|
allocationFailures |
Allocations refused because the pool had no free block (since start). | |
cgnTranslated |
boolean | True for an IPv4 pool in a VRF translated by on-box CGN. |
delegationLength |
Prefix length handed to each subscriber (32, 64 or the PD length). | |
description |
string | Free-text description. |
exclude |
Array<string> | Addresses or prefixes never allocated. |
family |
string | ipv4, ipv6-wan or ipv6-pd. |
free |
Blocks available. | |
held |
Of `used`, the blocks reserved for IPoE lines whose session has ended — IPv6 pools only (`protocols ipoe ipv6-reservation-hours`). The blocks in active use are `used` less `held` and the subnets' `offered` and `quarantined`. | |
name |
string | Pool name — the reference AAA returns (Framed-Pool and friends). |
size |
Allocatable blocks on this appliance (excluded addresses not counted). | |
subnets |
Array<AddressPoolSubnet> | The subnets this appliance allocates from, in preference order. |
used |
Blocks held: committed to sessions, on offer, quarantined, or reserved for a line whose session has ended (`held`). | |
utilisationPercent |
Used as a percentage of size. | |
vrf |
string | null | VRF the pool's addresses live in; null = the default table. |
AddressPoolAllocation#
| Name | Type | Description |
|---|---|---|
kind |
string | ipv4, ipv6-wan or ipv6-pd. |
prefix |
string | The block ("address/32", "prefix/64" or the delegated prefix). |
sessionId |
Holding session. | |
static |
boolean | A static address inside the pool rather than a pool allocation. |
username |
string | null | Subscriber username, when known. |
vrf |
string | null | The session's VRF; null = the default table. |
AddressPoolAllocationsPage#
| Name | Type | Description |
|---|---|---|
items |
Array<AddressPoolAllocation> | The page. |
limit |
The effective page size. | |
offset |
The offset this page was taken at. | |
total |
Allocations in the pool (before paging). |
AddressPoolReservation#
| Name | Type | Description |
|---|---|---|
circuit |
string | null | The physical circuit it was reserved on, `port:svlan:cvlan`; a circuit holds at most one reservation per pool. |
expiresUtc |
string(date-time) | When it lapses and the block returns to the pool. |
owner |
string | The pool owner it is held for: the line's access identity (`cid:…` Option-82 circuit-id, `user:…` IPoE username mode, or `port:…`). |
pool |
string | The pool the block belongs to. |
prefix |
string | The held block (the WAN /64 or the delegated prefix). |
reservedUtc |
string(date-time) | null | When the reservation was made (the session ended). |
AddressPoolReservationsCleared#
| Name | Type | Description |
|---|---|---|
cleared |
Held blocks returned to their pools. |
AddressPoolReservationsClearRequest#
| Name | Type | Description |
|---|---|---|
all |
boolean | Every reservation in every pool; give it alone. |
owner |
string | null | Only the reservation held for this owner. |
pool |
string | null | The pool whose reservations to release. Required unless `all`. |
prefix |
string | null | Only the reservation of this block. |
AddressPoolReservationsPage#
| Name | Type | Description |
|---|---|---|
items |
Array<AddressPoolReservation> | The page. |
limit |
The effective page size. | |
offset |
The offset this page was taken at. | |
total |
Reservations matching (before paging). |
AddressPoolSubnet#
| Name | Type | Description |
|---|---|---|
announce |
boolean | Announced into BGP as an aggregate. |
free |
Blocks available. | |
gateway |
string | null | The appliance's own address in the subnet — the router a lease for an address of it names; null when the subnet has none. |
held |
Blocks reserved for IPoE lines whose session has ended: given to nobody else until the line comes back or the reservation lapses. | |
offered |
Blocks held by an OFFER or a PPP negotiation not yet committed. | |
prefix |
string | The subnet (CIDR). |
quarantined |
Blocks declined by a DHCP client, out of service for an hour. | |
size |
Allocatable blocks in the subnet. | |
used |
Blocks held (committed, offered, quarantined or reserved). |
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 |
|---|---|
| Address pools |