Skip to content

Billing integration

A billing can drive the router in two ways:

  • The REST API on port 8880. New integrations use it, with services.
  • MK-api on port 8728: a MikroTik RouterOS API listener, for a billing that already provisions MikroTik routers and cannot be changed. It works with MAC-based clients.
  • Address: http://<router>:8880.

  • Every request carries the API key: header X-API-Key: <key> (or ?api_key= on GET). The key was printed by the installer and is in /opt/dtvsol/etc/config.php.

  • The billing server’s network must be on the allow-list:

    Terminal window
    dtvsol protect add XXX.XXX.XXX.25 "billing"
  • JSON in, JSON out.

  • Timeouts: at least 60 seconds per call (120 s is comfortable). Creating a service holds one OLT session (10–40 s), and the router talks to an OLT one session at a time. A call that arrives while the router is syncing or saving that OLT waits up to about 25 s more. That is not an error: do not retry early.

billing (support) billing (technician app) router OLT
1. create customer
and contract
2. installs the ONU, taps
"register ONU"
GET /services/unregistered --> asks every OLT -------> autofind
<-- list of ONTs {olt, pon, sn, vendor}
3. picks the serial
POST /services -------------> registers the ONT ---> ONT, service-port,
{ref, sn, olt, pon, plan} address, DHCP, CGNAT, rate limit
anti-spoofing
<-- 201 {service: {id, ipv4}, technician: {user_vlan}}
4. shows "ONU WAN = VLAN <user_vlan>, DHCP"
5. stores service.id
6. later, by id: plan change, suspend/resume, end date, delete, status, graph
Call Purpose
GET /services/unregistered[?olt=<name>] ONTs connected and not registered (about 3 s per OLT)
POST /services create a service (the one call)
GET /services/{id} status: record, plan and live state
POST /services/{id} change plan, names, end date, or retry
POST /services/{id}/suspend, /resume cut at the fiber and on the router, and restore
DELETE /services/{id}[?keep_ont=1] remove it; the id is never reused
GET /services/{id}/graph?period=hour|day|week|month|year a PNG of the traffic
GET /services?state=…&olt=…&q=…&fast=1 list; fast=1 skips the live probe

{id} accepts the service id, your ref, the serial, the contract or the IPv4 address.

Field Required Meaning
ref recommended your id for this service. Makes the call idempotent: repeating it returns the existing service (200, existing: true).
sn yes the ONT serial, 16 hex digits
olt when more than one OLT the OLT name
pon recommended frame/slot/port; looked up in autofind if left out
plan, or down_mbps + up_mbps yes a plan name, or speeds (plan_<down>_<up> is created if missing)
name yes the customer, as you want to see it on the router
contract, comment no free text, stored and searchable
user_vlan no the VLAN the ONU sends, when it is not the port’s
ipv6 no default true when the router has an IPv6 pool
iptv no the ONT’s second Ethernet port on the IPTV VLAN
expires no end date: suspended on that date, resumed when you push a later one

Example request:

{ "ref": "C-0001", "sn": "485754430A1B2C3D", "olt": "olt-1", "pon": "0/1/0",
"down_mbps": 200, "up_mbps": 200, "name": "Example Customer",
"contract": "C-0001", "ipv6": true, "expires": "2026-12-31" }

Store service.id from the answer, and show technician.user_vlan to the technician. The subscriber’s address (service.ipv4.address) is fixed for the life of the service. See Services for a full answer.

{ "plan": "plan_300_300" }
{ "down_mbps": 300, "up_mbps": 300 }
{ "name": "…", "contract": "…", "comment": "…", "ref": "…" }
{ "expires": "2026-11-30" }
{ "expires": "never" }
{ "retry": true }

A plan change moves the ONT to the new rate limit (a few seconds of interruption). The answer’s olt field says whether the OLT side succeeded. A 502 on suspend or resume means the router side was done and the OLT did not follow: retry.

Code Meaning What to do
400 a field is missing or invalid (error says which) fix the request
404 the serial is not in the OLT’s autofind table the ONU is not connected, not seen yet, or already registered
409 the serial already belongs to a service (returned), or the port cannot be used now use the returned id; otherwise ask the operator
502 the OLT refused or could not be reached retry later; nothing was created
500 the OLT side worked, the router side failed the service is in state error: {"retry": true} after the cause is fixed
507 no address left on that port ask the operator
  • Always send ref. A retry after a network timeout then never creates a second service.
  • Numbering is derived, never chosen. See Concepts.
  • The MAC address is not an input. If the customer replaces his router, the service keeps working with the same address and id.

MK-api listens on TCP 8728 and speaks enough of the MikroTik RouterOS API that a billing thinks it talks to a MikroTik. It turns the billing’s commands into calls to the router’s own API.

Scope: DHCP/IPoE only.

Billing command What the router does
/ip/dhcp-server/lease/add creates a client (MAC + address)
/ip/dhcp-server/lease/set (disabled) suspends or resumes the client
/ip/dhcp-server/lease/remove deletes the client
/ip/dhcp-server/lease/print lists the clients
/queue/simple/… or a lease rate-limit sets the speed: a plan mk_<down>m_<up>m is made for it
/ppp/… (PPPoE) refused

Set it up:

Terminal window
dtvsol mkapi # status
dtvsol mkapi set user billing password '<password>'
dtvsol mkapi set identity router-1

identity, model <m> and version <v> set what the router answers when the billing asks which MikroTik it is talking to. port <n> changes the port.

The billing’s address must be on the allow-list (dtvsol protect add). The listener runs as dtvsol-mkapi.service.