Skip to content

OLT API

The router drives its OLTs through the licensed vendor driver that ships with it. This page covers:

  • Operations — POST /olt/{op}: one operation on one OLT (read its state, add an ONT, tag a VLAN, …).
  • The registry — /olts: the OLTs this router knows by name, with their credentials sealed on the router.
  • Plan sync — /olt/sync: the router’s plans pushed to every registered OLT as profiles and rate tables.
  • Backups — /olt/backup, /olt/backups, /olt/diff: the OLTs’ configuration history.

Base URL, authentication (X-API-Key), error format and the action API are described in the API overview.

Every operation needs an OLT. The router picks it in this order:

  1. olt in the body (or header X-OLT-Name) — a registered OLT by name. An unknown name is 404.
  2. host, user, pass in the body (or headers X-OLT-Host, X-OLT-User, X-OLT-Pass), with optional protocol (telnet or ssh, default telnet; header X-OLT-Protocol) and port (the OLT’s TCP port; header X-OLT-Port). password is accepted as an alias of pass.
  3. Nothing — when exactly one OLT is registered, that one.

Otherwise the answer is 400 (“name a registered OLT (olt) or send host, user and pass on this call”).

A numeric port in the body is the OLT’s TCP port; a PON port such as "0/1/3" in port is an argument of the operation. pon is accepted as an alias for the PON port.

Name In Type Notes
olt body string A registered OLT’s name (see above).
host, user, pass body string One-off credentials instead of olt.
protocol body string telnet (default) or ssh.
vendor body string Driver vendor for one-off credentials; default huawei. A registered OLT uses its own.
timeout body integer Seconds, 10–300. Default 40; 180 for config, plan-sync and init.
raw body boolean Also return every command sent and the OLT’s reply (raw). Always included on failure.
dry_run body boolean Write operations that support it only plan the change and return what they would do.
force body boolean Override a guard where the operation allows it (see Shared OLTs).

Every operation answers the same envelope:

{
"ok": true,
"code": 200,
"op": "info",
"olt": { "host": "XXX.XXX.XXX.10", "name": "olt-1" },
"took_ms": 1790,
"result": { },
"error": null
}
  • code is 200 on success, 401 when the OLT refused the login, 502 for any other failure (the OLT’s error is in error, and raw holds the transcript). An unknown operation is 404 with the list of operations in ops.
  • After a successful write (other than save and dry runs) the answer carries "note": "not saved to the OLT's flash yet — run op \"save\" when done".

Write operations need the licence’s write feature, run one at a time per OLT, and are never retried on another transport once sent. Each call is logged on the router (operation, OLT, outcome — never credentials).

A registered OLT can carry this router’s S-VLAN (svlan) and be marked as another company’s (operator). On such an OLT the router only touches what is its own: VLAN operations on another S-VLAN are refused unless force=true; ONT operations refuse an ONT whose service-ports are on another S-VLAN (force never overrides that); exec needs force=true. Objects the router creates are named with its prefix (default dtvsol, or s<svlan> when an S-VLAN is set).

Lists the operations, which of them change the OLT, and how to call them. No OLT is contacted.

Terminal window
curl -H "X-API-Key: YOUR_API_KEY" "http://ROUTER-IP:8880/olt"
{
"ops": ["info", "autofind", "onus", "vlans", "serviceports", "profiles", "config", "run", "audit",
"boards", "pon-ports", "port-optical", "counters", "exec", "vlan-add", "vlan-del",
"port-vlan", "profile-add", "profile-del", "ont-add", "ont-del", "ont-reboot", "ont-desc",
"ont-optical", "ntp", "sysname", "save", "plan-sync", "init", "ont-activate",
"ont-deactivate", "ont-replan"],
"write_ops": ["exec", "vlan-add", "vlan-del", "port-vlan", "profile-add", "profile-del", "ont-add",
"ont-del", "ont-reboot", "ont-desc", "ntp", "sysname", "save", "plan-sync", "init",
"ont-activate", "ont-deactivate", "ont-replan"],
"usage": "POST /olt/{op} with JSON {host, user, pass, [port], [protocol: telnet|ssh], ...op args}; ..."
}

The OLT’s product, software version and patch, uptime, system name, boards, clock and NTP state.

Terminal window
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"olt": "olt-1"}' "http://ROUTER-IP:8880/olt/info"
{
"ok": true,
"code": 200,
"op": "info",
"olt": { "host": "XXX.XXX.XXX.10", "name": "olt-1" },
"took_ms": 1790,
"result": {
"product": "MA5608T",
"version": "V800R018C10",
"uptime": "35 day(s), 4 hour(s)",
"sysname": "olt-1",
"boards": [ { "slot": 0, "board": "GPFD", "status": "Normal" } ],
"time": "2026-09-28 12:00:00+00:00",
"ntp": "synchronized"
},
"error": null
}

With one-off credentials instead of a registered name:

Terminal window
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"host": "XXX.XXX.XXX.10", "user": "admin", "pass": "OLT_PASSWORD", "protocol": "ssh"}' \
"http://ROUTER-IP:8880/olt/info"

The ONTs the OLT sees but that are not registered yet (PON port, serial, vendor, when seen). Result: {"count": N, "onts": [...]}.

Terminal window
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"olt": "olt-1"}' "http://ROUTER-IP:8880/olt/autofind"

The registered ONTs: id, serial, run/config/match state. Result: {"count": N, "onts": [...]}.

Name In Type Notes
port body string Optional PON port frame/slot/port, e.g. 0/1/3. Without it, every PON board.
Terminal window
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"olt": "olt-1", "port": "0/1/3"}' "http://ROUTER-IP:8880/olt/onus"

The OLT’s VLAN table and the VLANs tagged on every uplink port. Result: {"count": N, "vlans": [...], "uplink_ports": {"0/3/0": {"vlans": [100, 101], "native": null}}}.

Terminal window
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"olt": "olt-1"}' "http://ROUTER-IP:8880/olt/vlans"

The service-ports (subscriber flows). Result: {"count": N, "service_ports": [...]}.

Terminal window
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"olt": "olt-1"}' "http://ROUTER-IP:8880/olt/serviceports"

The DBA, line and service profiles. Result: {"dba": [...], "line": [...], "service": [...]}.

Terminal window
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"olt": "olt-1"}' "http://ROUTER-IP:8880/olt/profiles"

The OLT’s full running configuration as text. Result: {"lines": N, "config": "..."}. Default timeout 180 s.

Terminal window
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"olt": "olt-1"}' "http://ROUTER-IP:8880/olt/config"

Runs one read-only display … command and returns its raw output. Anything that is not a display command is refused (use exec for configuration). Result: {"command": "...", "output": "..."}.

Name In Type Notes
command body string Required. Must start with display.
Terminal window
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"olt": "olt-1", "command": "display ont info 0 1 3 all"}' "http://ROUTER-IP:8880/olt/run"

Read only: what the OLT holds for this router on its S-VLAN — whether the VLAN exists and its type, the uplinks it is tagged on, its service-ports with their rate limits, the rate tables, whether DHCP option 82 is enabled, and the ONTs of the given PON ports. Used by the router’s doctor.

Name In Type Notes
svlan body integer Required. The S-VLAN to audit.
ports body array Optional PON ports whose ONTs to list, e.g. ["0/1/3"].
Terminal window
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"olt": "olt-1", "svlan": 400, "ports": ["0/1/3"]}' "http://ROUTER-IP:8880/olt/audit"
{
"ok": true,
"code": 200,
"op": "audit",
"result": {
"svlan": 400,
"exists": true,
"type": "smart",
"attribute": "stacking",
"uplinks": [ { "port": "0/3/0", "native_vlan": 1, "state": "up" } ],
"service_ports": [ { "index": 12, "state": "up", "pon": "0/1/3", "ont_id": 0, "gem": 1,
"flow_type": "vlan", "user_vlan": 100, "inner_vlan": 100,
"car": { "in": 11, "out": 10 } } ],
"option82": true,
"rates": { "10": { "cir": 112640, "pir": 112640 } },
"onts": [],
"plan_prefix": "dtvsol"
}
}

The OLT’s boards (slot, type, state).

Terminal window
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"olt": "olt-1"}' "http://ROUTER-IP:8880/olt/boards"

The PON ports and their state.

Name In Type Notes
port body string Optional: one PON port frame/slot/port; default every port.
Terminal window
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"olt": "olt-1"}' "http://ROUTER-IP:8880/olt/pon-ports"

The optical readings of the PON ports’ own transceivers.

Name In Type Notes
port body string Optional: one PON port; default every port.
Terminal window
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"olt": "olt-1", "port": "0/1/3"}' "http://ROUTER-IP:8880/olt/port-optical"

Traffic counters of the ports, or of the ONTs.

Name In Type Notes
port body string Optional: one PON port.
ont_id body integer Optional: one ONT’s counters (needs port).
uplinks body boolean Include the uplink ports.
onts body boolean Per-ONT counters for every ONT (of port if given) instead of the ports’ own.
Terminal window
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"olt": "olt-1", "uplinks": true}' "http://ROUTER-IP:8880/olt/counters"

An ONT’s optical readings: receive/transmit power, temperature, voltage. Result: {"port": "0/1/3", "onts": [...]}.

Name In Type Notes
port body string Required. PON port frame/slot/port.
ont_id body integer or "all" Optional; default every ONT on the port.
Terminal window
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"olt": "olt-1", "port": "0/1/3", "ont_id": 0}' "http://ROUTER-IP:8880/olt/ont-optical"

Nothing below is saved to the OLT’s flash until POST /olt/save. VLAN ids are 1–4094.

Normally you provision a subscriber with POST /services (see the Services API), which calls this for you and also sets up the router side.

Name In Type Notes
port body string Required. PON port, e.g. 0/1/3 (pon also accepted).
sn body string Required. The ONT serial as 16 hex digits.
vlan body integer Required. The PON port’s VLAN.
user_vlan body integer The VLAN the ONT sends; default vlan.
description body string ONT description.
plan body string A plan on this router: its profiles and rate limits are used (the rates include the router’s OLT headroom, default ×1.10). 404 if the plan does not exist.
down_kbps, up_kbps body integer Explicit rate limits instead of plan.
line_profile, srv_profile, profile_id body integer Explicit profile ids (profile_id sets both; default the vlan).
svlan body integer Outer VLAN; a registered OLT’s svlan is used when omitted.
iptv body boolean With a registered OLT: add the OLT’s IPTV VLAN (iptv_vlan) for this subscriber.
iptv_vlan body integer The IPTV VLAN explicitly.
eth_ports body integer Default 1.
gemport body integer Default 1.
dry_run body boolean Plan only.
Terminal window
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"olt": "olt-1", "port": "0/1/3", "sn": "ABCD123456789012", "vlan": 100, "plan": "plan_100_50", "description": "router-1 sub 42"}' \
"http://ROUTER-IP:8880/olt/ont-add"
{
"ok": true,
"code": 200,
"op": "ont-add",
"olt": { "host": "XXX.XXX.XXX.10", "name": "olt-1" },
"result": { "port": "0/1/3", "sn": "ABCD123456789012", "ont_id": 0, "vlan": 100, "cvlan": 100, "user_vlan": 100 },
"error": null,
"note": "not saved to the OLT's flash yet — run op \"save\" when done"
}
Name In Type Notes
port body string Required. PON port.
ont_id body integer Required.
force body boolean Also act on an ONT that has no service-port at all.
expect_svlan body integer One more S-VLAN counted as this router’s for this ONT.
dry_run body boolean Plan only.
Terminal window
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"olt": "olt-1", "port": "0/1/3", "ont_id": 0}' "http://ROUTER-IP:8880/olt/ont-del"

Result: {"port": "0/1/3", "ont_id": 0, "deleted": true, "service_ports_removed": [...]}.

Same parameters as ont-del (port, ont_id, force, expect_svlan). Result: {"port": "0/1/3", "ont_id": 0, "rebooted": true}.

Terminal window
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"olt": "olt-1", "port": "0/1/3", "ont_id": 0}' "http://ROUTER-IP:8880/olt/ont-reboot"

Parameters: port, ont_id, force, expect_svlan. Result: {"port": "0/1/3", "ont_id": 0, "active": true}. Resuming a service (POST /services/{id}/resume) calls this for you.

Terminal window
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"olt": "olt-1", "port": "0/1/3", "ont_id": 0}' "http://ROUTER-IP:8880/olt/ont-activate"

Parameters: port, ont_id, force, expect_svlan. Result: {"port": "0/1/3", "ont_id": 0, "active": false}. Suspending a service (POST /services/{id}/suspend) calls this for you.

Terminal window
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"olt": "olt-1", "port": "0/1/3", "ont_id": 0}' "http://ROUTER-IP:8880/olt/ont-deactivate"
Name In Type Notes
port body string Required.
ont_id body integer Required.
description body string The new description (empty clears it).
Terminal window
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"olt": "olt-1", "port": "0/1/3", "ont_id": 0, "description": "sub 42"}' \
"http://ROUTER-IP:8880/olt/ont-desc"

Changing a service’s plan (POST /services/{id} with plan) calls this for you.

Name In Type Notes
port body string Required.
ont_id body integer Required.
plan body string Required. The plan name.
down_kbps, up_kbps body integer Required. The new rate limits.
vlan body integer Required. The inner VLAN.
user_vlan body integer Default vlan.
svlan body integer Must be this router’s S-VLAN on a shared OLT.
expect_svlan body integer As for ont-del.
Terminal window
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"olt": "olt-1", "port": "0/1/3", "ont_id": 0, "plan": "plan_300_150", "down_kbps": 337920, "up_kbps": 168960, "vlan": 100, "svlan": 400}' \
"http://ROUTER-IP:8880/olt/ont-replan"
Name In Type Notes
vlan body integer Required.
type body string smart (default), standard, mux or super.
attribute body string common, stacking or qinq.
description body string Optional.
uplinks body array or string Uplink ports to tag it on, e.g. ["0/3/0"] or "0/3/0,0/3/1".
force body boolean Needed for a VLAN other than this router’s S-VLAN on a shared OLT.
dry_run body boolean Plan only.
Terminal window
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"olt": "olt-1", "vlan": 100, "uplinks": "0/3/0", "description": "PON 0/1/3"}' \
"http://ROUTER-IP:8880/olt/vlan-add"
Name In Type Notes
vlan body integer Required.
uplinks body array or string Uplink ports to untag it from first.
force body boolean As for vlan-add.
dry_run body boolean Plan only.
Terminal window
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"olt": "olt-1", "vlan": 100, "uplinks": ["0/3/0"]}' "http://ROUTER-IP:8880/olt/vlan-del"
Name In Type Notes
vlan body integer Required.
port body string Required. The port, e.g. 0/3/0.
remove body boolean Untag instead of tag.
force body boolean As for vlan-add.
dry_run body boolean Plan only.
Terminal window
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"olt": "olt-1", "vlan": 100, "port": "0/3/0"}' "http://ROUTER-IP:8880/olt/port-vlan"

Result: {"vlan": 100, "port": "0/3/0", "tagged": true}.

Name In Type Notes
vlan body integer Required.
dba body integer DBA profile id; default 5.
eth_ports body integer Default 1.
profile_id body integer Default the vlan.
force body boolean Override the ownership guard on a shared OLT.
Terminal window
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"olt": "olt-1", "vlan": 100, "dba": 5, "eth_ports": 1}' "http://ROUTER-IP:8880/olt/profile-add"
Name In Type Notes
profile_id body integer Required.
force body boolean Override the ownership guard on a shared OLT.
Terminal window
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"olt": "olt-1", "profile_id": 100}' "http://ROUTER-IP:8880/olt/profile-del"

On a shared OLT it needs force=true. A command containing ? is refused. Result: {"executed": N, "steps": [{"cmd": "...", "output": "..."}]}.

Name In Type Notes
commands body array or string Required. A list, or one text with commands separated by newlines or commas.
force body boolean Required on a shared OLT.
Terminal window
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"olt": "olt-1", "commands": ["vlan desc 100 description PON-0-1-3"]}' \
"http://ROUTER-IP:8880/olt/exec"
Name In Type Notes
server body string Required. NTP server address.
remove body boolean Remove instead of set.
timezone body string Optional time zone to set with it.
Terminal window
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"olt": "olt-1", "server": "10.0.0.1"}' "http://ROUTER-IP:8880/olt/ntp"

Result: {"server": "10.0.0.1", "set": true}.

Name In Type Notes
name body string Required. Letters, digits, ., _, -.
Terminal window
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"olt": "olt-1", "name": "olt-1"}' "http://ROUTER-IP:8880/olt/sysname"

Result: {"saved": true, "output": "..."}.

Terminal window
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"olt": "olt-1"}' "http://ROUTER-IP:8880/olt/save"

When plans is not given, the router’s own plans and OLT headroom are sent (and a registered OLT’s iptv_vlan). To sync every registered OLT at once use POST /olt/sync.

Name In Type Notes
dry_run body boolean Only list the commands it would run.
Terminal window
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"olt": "olt-1", "dry_run": true}' "http://ROUTER-IP:8880/olt/plan-sync"

With a registered OLT, missing values come from the registry (svlan, iptv_vlan, operator), the system name defaults to the OLT’s registered name, NTP to the router’s own address towards the OLT, and the plans to the router’s plans. On an OLT registered as another company’s (operator) the OLT-wide settings are left alone.

Name In Type Notes
apply body boolean Make the changes; default false (dry run).
svlan body integer This router’s S-VLAN.
iptv_vlan body integer IPTV VLAN.
uplinks body array or string Uplink ports to use.
sysname body string System name.
ntp body string NTP server.
timezone body string Time zone.
operator body boolean Treat the OLT as another company’s.
router_parent body string The router interface the OLT’s S-VLANs ride on.
Terminal window
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"olt": "olt-1", "svlan": 400, "uplinks": "0/3/0"}' "http://ROUTER-IP:8880/olt/init"

Result (dry run, trimmed): {"dry_run": true, "svlan": 400, "pon_ports": ["0/1/0", "0/1/1"], "uplinks": ["0/3/0"], "steps": [{"cmd": "..."}]}.

One OLT at a time. The same work runs by itself in the background after every plan change and on a timer. Also answers GET with the parameters in the query string.

Name In Type Notes
olt body or query string Only this registered OLT.
dry_run body or query boolean Only list the commands per OLT.
Terminal window
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"olt": "olt-1", "dry_run": true}' "http://ROUTER-IP:8880/olt/sync"
{
"ok": true,
"code": 200,
"dry_run": true,
"plans": [ { "name": "plan_100_50", "down_mbps": 100, "up_mbps": 50 } ],
"headroom": 1.1,
"olts": {
"olt-1": {
"ok": true,
"error": null,
"in_sync": false,
"executed": 0,
"dry_run": true,
"commands": ["..."],
"changes": { },
"notes": []
}
}
}

502 when any OLT failed; 404 when no OLT is registered or the named one is unknown.

Same as POST /olt/sync, with olt and dry_run in the query string.

Terminal window
curl -H "X-API-Key: YOUR_API_KEY" "http://ROUTER-IP:8880/olt/sync?dry_run=1"

The OLTs’ configurations are kept on the router as a history (one entry per change). The router backs them up by itself after changes; these calls read the history or take a backup now. olt may be omitted when exactly one OLT is registered (404 otherwise). Each also accepts POST with the parameters in the body.

Refused with 409 for an OLT registered as another company’s (operator).

Name In Type Notes
olt body or query string The registered OLT.
Terminal window
curl -X POST -H "X-API-Key: YOUR_API_KEY" "http://ROUTER-IP:8880/olt/backup?olt=olt-1"
{
"code": 200,
"olt": "olt-1",
"ok": true,
"changed": true,
"commit": "3f2a9c1",
"lines": 2140
}

502 when the configuration could not be read (or looked incomplete — then nothing is stored).

The backup history of an OLT, newest first, and its maintenance state.

Name In Type Notes
olt query string The registered OLT.
n query integer How many entries; default 30, 1–500.
Terminal window
curl -H "X-API-Key: YOUR_API_KEY" "http://ROUTER-IP:8880/olt/backups?olt=olt-1&n=10"
{
"ok": true,
"code": 200,
"olt": "olt-1",
"state": { },
"backups": [
{ "commit": "3f2a9c1", "at": "2026-09-28 12:00:00", "what": "olt-1: on request — 1 file changed, 3 insertions(+), 1 deletion(-)" }
]
}

What changed in an OLT’s configuration: at one backup (default the latest), or between two.

Name In Type Notes
olt query string The registered OLT.
rev query string A backup’s commit id (4–40 hex digits); default the latest.
to query string A second commit id: the diff between rev and to.
Terminal window
curl -H "X-API-Key: YOUR_API_KEY" "http://ROUTER-IP:8880/olt/diff?olt=olt-1&rev=3f2a9c1"
{ "ok": true, "code": 200, "olt": "olt-1", "diff": "3f2a9c1 2026-09-28 12:00:00\n...\n" }

With no backup yet: "diff": "" and "note": "no backup yet". 400 for a malformed commit id, 404 for an unknown one.

The registered OLTs. Passwords are never returned (has_pass is always true); for SNMP access only its version is shown. Each entry carries the result of its last plan sync.

Terminal window
curl -H "X-API-Key: YOUR_API_KEY" "http://ROUTER-IP:8880/olts"
{
"count": 1,
"olts": [
{
"name": "olt-1",
"vendor": "huawei",
"protocol": "telnet",
"host": "XXX.XXX.XXX.10",
"port": null,
"user": "admin",
"svlan": 400,
"iptv_vlan": 200,
"comment": "",
"product": "MA5608T",
"added": "2026-09-01 10:00:00",
"updated": "2026-09-20 09:00:00",
"has_pass": true,
"snmp": "v3",
"last_sync": { "at": "2026-09-28 11:45:00", "ok": true, "in_sync": true }
}
],
"headroom": 1.1,
"plans": 2
}

Unless force=true, the login is tested first (and new SNMP access gets its own test read); a failed test is 502 and nothing is stored. For an OLT this router owns (not operator), the router then also sets the OLT’s clock source.

Name In Type Notes
name body string Required. Lower-case letters, digits, ., _, -, max 32; starts with a letter or digit.
host body string Required. IP address or hostname.
user body string Required.
pass body string Required.
protocol body string telnet (default) or ssh.
port body integer TCP port, if not the protocol’s default.
svlan body integer This router’s S-VLAN on the OLT (1–4094, or null/"none").
iptv_vlan body integer IPTV VLAN (1–4094, or null/"none").
operator body boolean The OLT belongs to another company; the router only manages its own S-VLAN and profiles there.
parent body string The router interface the OLT’s S-VLANs ride on (must exist).
comment body string Free text.
snmp body object Optional SNMP access for the licensed driver (version v3 with user and auth/priv settings, or v2c/v1 with a community). null removes it.
force body boolean Store without the login test.
Terminal window
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"name": "olt-1", "host": "XXX.XXX.XXX.10", "user": "admin", "pass": "OLT_PASSWORD", "protocol": "ssh", "svlan": 400, "iptv_vlan": 200}' \
"http://ROUTER-IP:8880/olts"
{
"ok": true,
"code": 201,
"message": "OLT registered: olt-1",
"olt": { "name": "olt-1", "host": "XXX.XXX.XXX.10", "protocol": "ssh", "svlan": 400, "has_pass": true, "snmp": null },
"probe": { "product": "MA5608T" },
"ntp": { },
"next": "dtvsol olt sync --olt olt-1 (pushes the router's plans to it)"
}

Errors: 400 for invalid fields, 409 when the name already exists, 502 when the login test fails (“send force=true to store anyway”).

Same fields as POST /olts (except name, which comes from the path). The login is tested again unless force=true. Answers 200 with "message": "OLT updated: olt-1"; 404 for an unknown name.

Terminal window
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"svlan": 500, "comment": "rack 2"}' "http://ROUTER-IP:8880/olts/olt-1"

The name may also be given in the body as name (with DELETE /olts).

Terminal window
curl -X DELETE -H "X-API-Key: YOUR_API_KEY" "http://ROUTER-IP:8880/olts/olt-1"
{
"ok": true,
"code": 200,
"message": "OLT removed: olt-1",
"note": "its profiles on the OLT itself are left as they are"
}

The action API takes its parameters in the query string. Because that puts credentials in a URL, prefer the REST routes above; with a registered OLT, only olt=<name> is needed.

Action Query parameters Same as
action=olt-<op> (e.g. action=olt-info) olt, or host/user/pass; plus the operation’s arguments POST /olt/{op}
action=olt-sync olt, dry_run POST /olt/sync
action=olt-backup olt POST /olt/backup
action=olt-backups olt, n GET /olt/backups
action=olt-diff olt, rev, to GET /olt/diff
action=olts-list — GET /olts
action=olts-add name, host, user, pass, protocol, port, svlan, iptv_vlan, … POST /olts
action=olts-set name, fields to change POST /olts/{name}
action=olts-del name DELETE /olts/{name}

This site was written with the help of AI and checked by our team.