Services
A service is one customer on one ONT, with one speed, one fixed address and a permanent id. One call registers the ONT on its OLT (profiles, rate limit, QinQ service-port) and sets up the router side: the port’s VLAN interface, DHCP with Option 82, IPv6 and a delegated prefix, CGNAT, accounting and anti-spoofing. Read Concepts first for the numbering.
Before the first service
Section titled “Before the first service”- The OLT is registered with this router’s S-VLAN:
dtvsol olt add … --svlan <n>. See OLTs. - The S-VLAN interface
vlan<svlan>exists on the port or bond facing the OLT. - The services’ address pools are set in
/opt/dtvsol/etc/config.php:svc_ipv4_pool(for example100.64.0.0/10), and for IPv6svc_ipv6_poolandsvc_pd_pool. Without an IPv6 pool, services are IPv4 only.
The technician’s flow
Section titled “The technician’s flow”-
The technician connects and powers the ONU.
-
He lists the ONTs that are connected and not yet registered:
Terminal window dtvsol service unregistered -
He picks the serial and creates the service:
Terminal window dtvsol service add 485754430A1B2C3D --name "Example Customer" --plan plan_200_200 \--olt olt-1 --pon 0/1/0 --ref C-0001 --contract C-0001 -
The command prints the VLAN to set on the ONU’s WAN, with DHCP. The ONU then receives its fixed address.
CLI reference
Section titled “CLI reference”dtvsol service unregistered [--olt n]dtvsol service add <sn> --name "..." (--plan p | --down d --up u) [--olt n] [--pon f/s/p] [--user-vlan v] [--ref r] [--contract c] [--expires YYYY-MM-DD|never] [--comment ...] [--iptv] [--no-ipv6]dtvsol service list [--state active|suspended|error] [--olt n] [-q text] [--fast] [--json]dtvsol service get <id>dtvsol service set <id> [--plan p | --down d --up u] [--name] [--contract] [--expires] [--comment] [--retry]dtvsol service suspend <id> | resume <id>dtvsol service del <id> [--keep-ont]dtvsol service graph <id> [hour|day|week|month|year] [out.png] [--olt|--errors]Notes:
<id>can be the service id, yourref, the ONT serial, the contract, the address or the interface.--down/--upinstead of--plancreatesplan_<down>_<up>if it does not exist.--poncan be left out: the router finds the serial in the OLT’s autofind table.--user-vlanis for an ONU that already sends another VLAN (for example when taking over an existing network). The OLT translates it; the ONU is not touched.--refmakes the call idempotent: the samerefreturns the same service.--iptvputs the ONT’s second Ethernet port on the OLT’s IPTV VLAN.- A plan change moves the ONT to the new rate limit on the OLT. The customer sees a few seconds of interruption.
- Suspending deactivates the ONT on the OLT and blocks the address on the router. With an end
date (
--expires), the router suspends by itself on that date and resumes when you push a later date. service graph --oltshows the ONT’s traffic as the OLT counts it;--errorsits fiber errors (BIP, FEC).
A subscriber whose ONT was provisioned by hand can still be recorded:
dtvsol service add none --svlan 1000 --pon 0/1/0 --ont-id 7 --name "Example Customer" --plan plan_100_50The API
Section titled “The API”The same operations are available over HTTP on port 8880. Every request carries the API key in
the X-API-Key header. The caller’s network must be on the allow-list (dtvsol protect add).
Give every call at least 60 seconds. Creating a service holds one OLT session (10–40 s), and may wait for the router’s own OLT work.
Unregistered ONTs:
curl -s -H "X-API-Key: $KEY" "http://XXX.XXX.XXX.10:8880/services/unregistered?olt=olt-1"{ "ok": true, "count": 1, "onts": [ { "olt": "olt-1", "pon": "0/1/0", "sn": "485754430A1B2C3D", "vendor": "HWTC", "seen_at": "2026-09-25 10:12:03+00:00", "svlan": 1000, "cvlan": 116 } ], "errors": {} }Create a service:
curl -s -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \ "http://XXX.XXX.XXX.10:8880/services" -d '{ "ref": "C-0001", "sn": "485754430A1B2C3D", "olt": "olt-1", "pon": "0/1/0", "down_mbps": 200, "up_mbps": 200, "name": "Example Customer", "ipv6": true, "expires": "2026-12-31" }'The answer (201) carries the service. Store service.id. Show
technician.user_vlan to the technician:
{ "ok": true, "message": "Service created", "service": { "id": "svc_d320fcbd", "ref": "C-0001", "olt": "olt-1", "pon": "0/1/0", "ont_id": 7, "svlan": 1000, "cvlan": 116, "user_vlan": 116, "iface": "v1000.116", "ipv4": { "network": "100.64.16.0/24", "gateway": "100.64.16.1", "address": "100.64.16.9" }, "ipv6": { "link": "XXXX:XXXX:0:116::/64", "pd": "XXXX:XXXX:1:1600::/56" }, "plan": "plan_200_200", "state": "active" }, "technician": { "user_vlan": 116, "note": "set the ONU's WAN to VLAN 116, DHCP; it receives 100.64.16.9" } }Other calls:
| Call | What it does |
|---|---|
GET /services/{id} |
the record, plus live state: link, online, MAC seen, DHCP lease |
POST /services/{id} |
change plan (or down_mbps/up_mbps), name, contract, comment, expires, or {"retry": true} |
POST /services/{id}/suspend, /resume |
cut and restore |
DELETE /services/{id} |
remove it everywhere (?keep_ont=1 leaves the ONT registered) |
GET /services/{id}/graph?period=day |
a PNG of the traffic |
GET /services?state=active&olt=olt-1&q=text&fast=1 |
the list |
Error codes to handle: 400 bad field, 404 serial not in autofind, 409 serial already
belongs to a service (the answer carries it), 502 the OLT refused or could not be reached
(nothing was created), 500 the OLT side worked but the router side failed (the service exists
in state error: fix the cause, then {"retry": true}), 507 no address left on that port.
The full integration guide for billing teams is in Billing integration.