Skip to content

Networks API

These endpoints decide which interfaces the router serves with DHCP (IPv4) and DHCPv6 + router advertisements (IPv6), which addresses the pools hand out, how IPv6 prefix delegation is split between VLANs, and which DNS resolvers subscribers are given. Base URL, authentication and the error format are described in the API overview.

Every change is checked before it takes effect: the DHCP configuration is tested and the service restarted, and if either step fails the previous file is put back and the answer says … — rolled back. A 5xx answer can carry broken_data_files, naming router data files that do not parse.

Interfaces are addressed by name (vlan110, svlan300.10, bond0…). For VLANs, see VLANs, IPs and routes — adding a VLAN with an address serves it automatically.

Every IPv4 network configured on the router’s interfaces, with the IPv6 network of the same interface when it has one.

Terminal window
curl -H "X-API-Key: YOUR_API_KEY" http://ROUTER-IP:8880/networks
{
"count": 1,
"networks": [
{
"iface": "vlan110",
"gateway": "100.64.8.1",
"subnet": "100.64.8.0",
"mask": "255.255.255.0",
"cidr": 24,
"network": "100.64.8.0/24",
"bcast": "100.64.8.255",
"ipv6": "XXXX:XXXX:110::/64",
"gateway6": "XXXX:XXXX:110::1"
}
]
}

Each IPv4 network and whether DHCP actually serves it: dhcp_active is true only when the subnet is in the DHCP configuration and the interface is in the DHCP listen list. The same for DHCPv6 when the interface has an IPv6 network.

Terminal window
curl -H "X-API-Key: YOUR_API_KEY" http://ROUTER-IP:8880/interfaces
{
"count": 1,
"interfaces": [
{
"iface": "vlan110",
"gateway": "100.64.8.1",
"network": "100.64.8.0/24",
"cidr": 24,
"in_dhcp_conf": true,
"in_dhcp_listen": true,
"dhcp_active": true,
"network6": "XXXX:XXXX:110::/64",
"gateway6": "XXXX:XXXX:110::1",
"in_dhcp6_conf": true,
"in_dhcp6_listen": true,
"dhcp6_active": true
}
]
}

GET /net and GET /net6 give the same answer.

Every link on the router (physical ports, bonds, VLANs, S-VLANs, C-VLANs, USB, loopback) with its state, VLAN tag, addresses and counters.

Terminal window
curl -H "X-API-Key: YOUR_API_KEY" http://ROUTER-IP:8880/iface
{
"interfaces": [
{
"name": "vlan110",
"type": "vlan",
"status": "UP",
"parent": "bond0",
"ips": ["100.64.8.1/24"],
"ips6": ["XXXX:XXXX:110::1/64"],
"vlan_id": 108,
"vlan_proto": "802.1Q",
"mtu": 1500,
"speed_mbps": null,
"rx_bytes": 123456789,
"tx_bytes": 987654321
}
]
}

type is one of physical, vlan, svlan, cvlan, usb, loopback. status is UP only when the link is both up and has carrier.

Tests the DHCP configuration and restarts the DHCP service. Any other /dhcp/… path answers 404 Use /dhcp/reload.

Terminal window
curl -X POST -H "X-API-Key: YOUR_API_KEY" http://ROUTER-IP:8880/dhcp/reload
{ "ok": true, "message": "DHCP reloaded" }

On failure: 500 with error (DHCP config test failed or DHCP restart failed) and detail.

Serves the IPv4 network already configured on an interface: its subnet block is added to the DHCP configuration and the interface to the listen list. If the subnet is already there, only the listen list is updated.

Name In Type Notes
iface body string Interface that carries the IPv4 address, e.g. vlan110.
label body string Optional text written as a comment on the subnet block.
Terminal window
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"iface":"vlan110","label":"OLT 1 PON 0/1/3"}' \
http://ROUTER-IP:8880/net
{
"ok": true,
"code": 201,
"message": "Network 100.64.8.0/24 added on vlan110",
"network": { "iface": "vlan110", "gateway": "100.64.8.1", "network": "100.64.8.0/24", "cidr": 24 },
"label": "OLT 1 PON 0/1/3"
}

Errors: 404 when the interface has no IPv4 address; 500 when the configuration test or restart fails (rolled back).

Name In Type Notes
iface body string Interface to stop serving.
Terminal window
curl -X DELETE -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"iface":"vlan110"}' http://ROUTER-IP:8880/net
{
"ok": true,
"code": 200,
"message": "Network 100.64.8.0/24 removed from vlan110",
"network": { "iface": "vlan110", "network": "100.64.8.0/24" }
}

Errors: 409 while clients are still registered on the interface (Cannot remove: N client(s) registered on vlan110. Delete them first.); 404 when the interface has no IPv4 address; 500 when the subnet block is not found or the DHCP test/restart fails.

Adds the interface’s IPv6 network to DHCPv6, with an address pool derived from the network (for a /64: ::1000 to ::ffff), and updates router advertisements. If the other DHCPv6 subnets already carry name servers and no global IPv6 resolver is set, the new subnet inherits them.

Name In Type Notes
iface body string Interface that carries a global IPv6 address.
Terminal window
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"iface":"vlan110"}' http://ROUTER-IP:8880/net6
{
"ok": true,
"code": 201,
"message": "IPv6 network XXXX:XXXX:110::/64 added on vlan110 (DHCPv6 + radvd)",
"network6": { "iface": "vlan110", "gateway": "XXXX:XXXX:110::1", "prefix": 64, "network": "XXXX:XXXX:110::/64" },
"radvd": { "ok": true, "message": "radvd reloaded" },
"pool": "XXXX:XXXX:110::1000 - XXXX:XXXX:110::ffff",
"dns": "XXXX:XXXX::53"
}

When no pool can be derived the answer carries warning instead of pool; when there is no resolver to inherit, dns is null and a note says so. Errors: 404 No IPv6 address on interface '…'; 500 when the DHCPv6 test or restart fails (rolled back).

Removes the interface from DHCPv6. The subnet6 block is removed unless another served interface uses the same network; the interface’s prefix-delegation range is released.

Name In Type Notes
iface body string Interface to stop serving over IPv6.
Terminal window
curl -X DELETE -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"iface":"vlan110"}' http://ROUTER-IP:8880/net6
{
"ok": true,
"code": 200,
"message": "IPv6 network XXXX:XXXX:110::/64 removed from vlan110",
"radvd": { "ok": true, "message": "radvd reloaded" },
"removed_pd_pool": { "network6": "XXXX:XXXX:110::/64", "start": "XXXX:XXXX:b:1000::", "end": "XXXX:XXXX:b:10ff::", "size": 256 }
}

Sets the address range handed out on an interface’s IPv6 subnet. Without start/end the range is derived from the network. Parameters are read from the body, then the query string.

Name In Type Notes
iface body or query string Interface whose subnet6 block exists (see POST /net6).
start body or query IPv6 Optional first address; must be inside the network.
end body or query IPv6 Optional last address; must be inside the network.
Terminal window
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"iface":"vlan110"}' http://ROUTER-IP:8880/net6/pool
{
"ok": true,
"code": 200,
"message": "pool added on XXXX:XXXX:110::/64",
"iface": "vlan110",
"network": "XXXX:XXXX:110::/64",
"pool": "XXXX:XXXX:110::1000 - XXXX:XXXX:110::ffff",
"dns_added": false
}

Errors: 400 for an invalid or out-of-network address, or when no pool can be derived; 404 when the interface has no IPv6 address or no subnet6 block.

Sets the valid and preferred lifetimes DHCPv6 gives out (addresses and delegated prefixes) and updates router advertisements. GET /net6/lease takes the same parameters from the query string.

Name In Type Notes
valid body integer Valid lifetime in seconds, at least 120.
preferred body integer Optional; defaults to half of valid, cannot exceed it.
Terminal window
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"valid":86400,"preferred":43200}' http://ROUTER-IP:8880/net6/lease
{
"ok": true,
"code": 200,
"message": "DHCPv6 lifetimes updated",
"changed": ["default-lease-time = 86400", "preferred-lifetime = 43200", "dhcp-renewal-time = 21600", "dhcp-rebinding-time = 34560"],
"radvd": { "ok": true, "message": "radvd reloaded" },
"note": "existing leases keep their old lifetime until the client next renews"
}

Delegated prefixes (by default /64s) come from one router-wide pool set in the router configuration (pd_pool, pd_len). Each VLAN gets a slice of that pool (default pd_slice prefixes); the first pd_reserve prefixes are kept back for prefixes pinned to single clients.

The pool, its capacity, each VLAN’s slice, the pinned prefixes and the delegated routes the kernel holds now.

Terminal window
curl -H "X-API-Key: YOUR_API_KEY" http://ROUTER-IP:8880/pd
{
"pool": "XXXX:XXXX:a::/48",
"prefix_len": 64,
"usable": true,
"reserved_for_pinned": 4096,
"default_slice": 256,
"capacity": {
"prefixes_total": 65536,
"prefixes_reserved": 4096,
"prefixes_used": 256,
"prefixes_free": 61184,
"largest_free_run": 61184,
"vlans_at_default_slice": 240,
"vlans_free_at_default_slice": 239
},
"per_vlan": {
"vlan110": { "network6": "XXXX:XXXX:110::/64", "index": 4096, "slice": 0, "start": "XXXX:XXXX:a:1000::", "end": "XXXX:XXXX:a:10ff::", "len": 64, "size": 256 }
},
"pinned": [{ "mac": "AA:BB:CC:DD:EE:FF", "hostname": "cpe-1", "prefix6": "XXXX:XXXX:a:5::/64" }],
"live_routes": ["XXXX:XXXX:a:1000::/64 via fe80::1 dev vlan110 proto dhcp metric 1024"],
"live_count": 1
}

Enables prefix delegation on an interface that already has DHCPv6 (POST /net6). Calling it again with a new size re-allocates the slice.

Name In Type Notes
iface body string Interface with a subnet6 block.
size body integer Optional number of prefixes, a power of two (256, 512, 1024…); default is the configured slice.
Terminal window
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"iface":"vlan110","size":256}' http://ROUTER-IP:8880/pd
{
"ok": true,
"code": 201,
"message": "prefix delegation enabled on vlan110",
"iface": "vlan110",
"network": "XXXX:XXXX:110::/64",
"pool": "XXXX:XXXX:a:1000:: - XXXX:XXXX:a:10ff::",
"prefix_len": 64,
"capacity": 256,
"next": "set the CPE Site Prefix Type to \"Delegated\""
}

When the slice moved, replaced and warning are added (CPEs keep their old prefix until the lease expires; run a sync). Errors: 400 when size is not a power of two; 404 with no subnet6 block; 507 when the pool is exhausted (with requested and largest_free_run).

Name In Type Notes
iface body string Interface that already delegates.
size body integer New number of prefixes (power of two).
Terminal window
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"iface":"vlan110","size":1024}' http://ROUTER-IP:8880/pd/resize

The answer is the same as POST /pd. Errors: 400 without size; 404 when the interface has no delegation; 409 when it already holds that many prefixes.

Name In Type Notes
iface body string Interface to stop delegating on.
Terminal window
curl -X DELETE -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"iface":"vlan110"}' http://ROUTER-IP:8880/pd
{
"ok": true,
"code": 200,
"message": "prefix delegation removed from vlan110",
"note": "delegated routes are withdrawn as their leases expire"
}

Gives a client (by MAC) the same delegated prefix every time. Without prefix, the first free prefix in the reserved band is taken. GET /pd/assign takes the same parameters from the query string.

Name In Type Notes
mac body string A registered client’s MAC.
prefix body IPv6 prefix Optional; must have the delegated length and lie inside the pool. The length may be omitted.
Terminal window
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"mac":"AA:BB:CC:DD:EE:FF","prefix":"XXXX:XXXX:a:5::/64"}' \
http://ROUTER-IP:8880/pd/assign
{
"ok": true,
"code": 200,
"message": "pinned XXXX:XXXX:a:5::/64 to AA:BB:CC:DD:EE:FF",
"mac": "AA:BB:CC:DD:EE:FF",
"prefix6": "XXXX:XXXX:a:5::/64"
}

Errors: 404 unknown client; 400 invalid or out-of-pool prefix; 409 prefix pinned to another client; 507 no free prefix in the reserved band.

Name In Type Notes
mac body string Client whose pinned prefix is removed.
Terminal window
curl -X DELETE -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"mac":"AA:BB:CC:DD:EE:FF"}' http://ROUTER-IP:8880/pd/assign
{ "ok": true, "code": 200, "message": "unpinned XXXX:XXXX:a:5::/64 from AA:BB:CC:DD:EE:FF" }

Errors: 404 when the client has no pinned prefix.

Runs the delegated-route reconciler now and returns its output. Any method on /pd/sync runs it.

Name In Type Notes
dry query 1 Only report what would change.
Terminal window
curl -X POST -H "X-API-Key: YOUR_API_KEY" "http://ROUTER-IP:8880/pd/sync?dry=1"
{
"ok": true,
"code": 200,
"dry_run": true,
"output": ["…the reconciler's report, one line per entry…"]
}

The resolvers subscribers receive over DHCP and DHCPv6: a global default, and optional per-VLAN overrides.

What each served VLAN is actually given, where it comes from (per-vlan, global or none), and which served VLANs get no resolver at all.

Terminal window
curl -H "X-API-Key: YOUR_API_KEY" http://ROUTER-IP:8880/dns
{
"global": { "ipv4": "XXX.XXX.XXX.53, XXX.XXX.XXX.53", "ipv6": "XXXX:XXXX::53", "domain": "example.net" },
"per_vlan": { "ipv4": { "100.64.9.0": "XXX.XXX.XXX.53" }, "ipv6": {} },
"effective": [
{ "iface": "vlan110", "enabled": true, "ipv4": "XXX.XXX.XXX.53, XXX.XXX.XXX.53", "ipv4_source": "global", "ipv6": "XXXX:XXXX::53", "ipv6_source": "global" }
],
"serving_no_resolver": []
}
Name In Type Notes
v4 body string or list IPv4 resolvers, comma-separated or a JSON list.
v6 body string or list IPv6 resolvers.
domain body string Search domain.
apply body string Optional: all drops per-VLAN overrides so every VLAN follows the default; missing changes nothing further.
iface body string If given, sets a per-VLAN override instead (same as POST /dns/{iface}).

At least one of v4, v6, domain is required.

Terminal window
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"v4":"XXX.XXX.XXX.53,XXX.XXX.XXX.53","v6":"XXXX:XXXX::53","domain":"example.net"}' \
http://ROUTER-IP:8880/dns
{
"ok": true,
"code": 200,
"message": "resolvers updated",
"changed": ["ipv4 -> XXX.XXX.XXX.53, XXX.XXX.XXX.53", "domain -> example.net", "ipv6 -> XXXX:XXXX::53"],
"note": "clients pick this up at their next DHCP renewal",
"status": { "ipv4": "XXX.XXX.XXX.53, XXX.XXX.XXX.53", "ipv6": "XXXX:XXXX::53", "domain": "example.net" }
}

With apply, applied_to lists the VLANs whose overrides were dropped. Without it, a warning and shadowing list name VLANs whose own IPv6 resolvers hide the new default.

Name In Type Notes
iface path string Served VLAN interface, e.g. vlan130.
v4 body string or list IPv4 resolvers for this VLAN.
v6 body string or list IPv6 resolvers for this VLAN.
Terminal window
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"v4":"XXX.XXX.XXX.53"}' http://ROUTER-IP:8880/dns/vlan130
{
"ok": true,
"code": 200,
"message": "resolvers set on vlan130",
"iface": "vlan130",
"override": { "ipv4": "XXX.XXX.XXX.53" },
"note": "overrides the global resolvers for this VLAN only"
}

Errors: 400 without v4/v6 or with an invalid address; 404 when the interface, its network or its subnet block does not exist.

Name In Type Notes
iface path string VLAN interface.
Terminal window
curl -X DELETE -H "X-API-Key: YOUR_API_KEY" http://ROUTER-IP:8880/dns/vlan130
{
"ok": true,
"code": 200,
"message": "override removed from vlan130",
"removed": ["ipv4"],
"now_inherits": { "ipv4": "XXX.XXX.XXX.53, XXX.XXX.XXX.53", "ipv6": "XXXX:XXXX::53", "domain": "example.net" }
}

Errors: 404 when the VLAN has no override.

Name In Type Notes
global body string v4, v6, domain or all (all also removes existing IPv6 resolvers).
iface body string Alternatively, the VLAN whose override to remove.
Terminal window
curl -X DELETE -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"global":"domain"}' http://ROUTER-IP:8880/dns
{
"ok": true,
"code": 200,
"message": "global resolvers cleared: domain",
"cleared": ["domain"],
"global_now": { "ipv4": "XXX.XXX.XXX.53, XXX.XXX.XXX.53", "ipv6": "XXXX:XXXX::53", "domain": null },
"serving_no_resolver": []
}

Errors: 400 when neither global nor an interface is given, or global has another value; 404 when nothing of that kind was set.

Action Query parameters Same as
action=networks — GET /networks
action=interfaces — GET /interfaces
action=iface-list — GET /iface (without the counters)
action=reload — POST /dhcp/reload
action=add-net iface, label POST /net
action=remove-net iface DELETE /net
action=net6-add iface POST /net6
action=net6-del iface DELETE /net6
action=net6-pool iface, start, end POST /net6/pool
action=net6-lease valid, preferred POST /net6/lease
action=net6-dns servers, domain or clear_domain=1 Sets only the DHCPv6 resolvers/domain
action=pd-list — GET /pd
action=pd-add iface, size POST /pd
action=pd-resize iface, size POST /pd/resize
action=pd-del iface DELETE /pd
action=pd-assign mac, prefix POST /pd/assign
action=pd-unassign mac DELETE /pd/assign
action=pd-sync dry=1 POST /pd/sync
action=dns-list — GET /dns
action=dns-set v4, v6, domain, apply, or iface + v4/v6 POST /dns, POST /dns/{iface}
action=dns-del iface, or global=v4|v6|domain|all DELETE /dns/{iface}, DELETE /dns