Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.fyberpay.com/llms.txt

Use this file to discover all available pages before exploring further.

FyberPay communicates with MikroTik routers via the RouterOS REST API, introduced in RouterOS 7.1. For RouterOS 6.x devices, FyberPay uses the legacy API port. Each router connects over an encrypted SSTP management tunnel, so the API is never exposed to the public internet.

Supported RouterOS Versions

VersionAPI MethodNotes
RouterOS 7.1+REST API (HTTP/HTTPS)Recommended. Full feature support.
RouterOS 6.xREST API via www serviceRequires /ip service set www enabled.
RouterOS 7.x is recommended for all new deployments. FyberPay uses the /rest/ endpoint prefix for all API calls, which requires the www or www-ssl service to be enabled on the router.

Architecture Overview

MikroTik Router                    FyberPay Platform
+------------------+               +------------------+
| RouterOS REST API|<-- SSTP ----->| RouterOS Service |
| (port 80/443)    |   Tunnel      | (circuit breaker)|
+------------------+               +------------------+
| PPPoE Server     |               | Provisioning Svc |
| RADIUS Client    |               | CoA Service      |
| Firewall / Queue |               | RADIUS DB        |
+------------------+               +------------------+
FyberPay connects to each router through an SSTP tunnel. The router’s REST API listens on the tunnel IP (10.99.x.x subnet), never on a public interface.

Connection Setup

1

Register the NAS device

In the FyberPay admin dashboard, navigate to Network → Gateways and click Add Device. The wizard runs in four steps: type → name → provision → services. Provide:
  • Device name: a human-readable label (e.g. “Westlands-POP-1”)
  • IP address: the router’s WAN IP (used for RADIUS NAS registration)
  • RADIUS secret: shared secret for RADIUS authentication
  • CoA port: default is 3799
2

Run the bootstrap script

FyberPay generates a RouterOS provisioning script for each device. Copy and paste it into the router’s terminal. The script (BOOTSTRAP_VERSION=2, current) is tunnel-first: it brings the SSTP management tunnel up before touching anything else, so a partial bootstrap leaves the router reachable for retry. Steps:
  1. SSTP tunnel creation with a dedicated PPP profile (fyberpay-tunnel)
  2. RADIUS client configuration (authentication port 1812, accounting port 1813)
  3. REST API user creation with scoped permissions
  4. Firewall rules to allow tunnel traffic, ordered so the tunnel rule lands first
The SSTP client must use the dedicated fyberpay-tunnel PPP profile. Using profile=default causes IPCP negotiation failures because the default profile may have hardcoded addresses that conflict with the tunnel’s dynamic IP assignment.
Once a device is bootstrapped, FyberPay’s firewall reconciler keeps the FyberPay-managed firewall rules in lockstep with the platform’s view: drift (a rule deleted on the router, or one shifted out of order) is reported on the device’s detail page and can be fixed with one click. The reconciler only touches rules it owns (tagged comment=FyberPay-fw:*); the operator’s hand-rolled firewall is never modified.
3

Configure the REST API user

The bootstrap script creates an API user with a custom group called fyberpay-api. This group has the following policies:
read, write, api, rest-api
Policies explicitly denied: ftp, reboot, policy, test, password, sniff, sensitive, romon.The REST API service is restricted to the tunnel subnet:
/ip service set www disabled=no port=80 address=10.99.0.0/16
4

Verify connectivity

After the tunnel establishes, use the Ping button in FyberPay’s NAS device detail page. FyberPay calls GET /rest/system/resource on the router and reports the response time.

API Port Configuration

PortProtocolUse Case
80HTTPDefault REST API port over SSTP tunnel
443HTTPSREST API with TLS (self-signed certs accepted)
8728APILegacy MikroTik API protocol (RouterOS 6.x)
8729API-SSLLegacy API with TLS
FyberPay auto-detects the protocol based on the configured port. Ports 443 and 8729 use HTTPS; all others use HTTP. Self-signed certificates are accepted since traffic flows over the encrypted SSTP tunnel.

What FyberPay Reads from the Router

FyberPay polls the following data from each connected router:
Endpoint: GET /rest/system/resourceRetrieves CPU load, memory usage (total/free), uptime, RouterOS version, board name, and architecture. Displayed on the fleet dashboard.
Endpoint: GET /rest/ppp/activeLists all active PPPoE/PPTP/L2TP sessions with username, service type, caller ID, assigned IP, uptime, and encoding. Used for subscriber session monitoring.
Endpoint: GET /rest/interfaceReturns all interfaces with name, type, running/disabled status, TX/RX byte counters, packet counts, link-down count, and MTU.
Endpoint: GET /rest/ip/dhcp-server/leaseLists active DHCP leases with IP address, MAC address, hostname, status, and expiry time.
Endpoint: GET /rest/queue/simpleReads all simple queues with name, target address, max-limit, and burst-limit. Used for bandwidth plan enforcement visibility.
Endpoint: GET /rest/interface/pppoe-server/serverLists configured PPPoE server instances with service name, bound interface, and disabled state.

What FyberPay Writes to the Router

FyberPay’s writes to the router are driven by the NasService model: one row per customer-facing service (PPPoE, Hotspot, or CPE Management), reconciled against live router state by the NasService Reconciler. Operators create services in the FyberPay admin UI; the reconciler translates each service into the right combination of PPPoE servers, hotspot servers, IP addresses, pools, DHCP, VLAN sub-interfaces, walled-garden rules, and bridges on the live router.

The NasService model

Each service is one row in the nas_services table with these fields:
FieldMeaning
typepppoe, hotspot, or cpe-management
parentInterfaceThe interface on the router the service binds to. Can be an ether port (ether2), an SFP port (sfp1), a VLAN sub-interface (vlan100-mgmt), or an operator-managed bridge (bridge-customer).
vlanIdOptional VLAN tag. If set, the reconciler creates a VLAN sub-interface as the binding point.
subnet, gateway, poolStart, poolEndAuto-allocated from 10.50.0.0/16 (customer) or 10.20.0.0/16 (management). Operator can override under “Advanced”.
statependingactive (or failed / degraded if the reconciler hits an error or detects drift).
Each NasService has its own RouterOS resources, named with a deterministic 8-hex slug derived from the service id. For example, the PPPoE server for service 5d8f2a1e-... is named pppoe-svc-5d8f2a1e. Every resource the reconciler creates carries comment=FyberPay-svc:<service-id> so ownership is unambiguous on the router.

The reconciler primitives

Three idempotent primitives, all in apps/api/src/network/nas-services/reconciler.ts:
  • applyService(serviceId): read live state for the service tag, compute a diff against the desired state, execute the diff. Used on create, update, manual reconcile, and drift recovery.
  • removeService(serviceId): tear down every resource carrying the service tag. Used on delete.
  • reconcileDevice(deviceId): scan the device for orphaned resources (carrying a service tag for a service that no longer exists in the database) and remove them.

Bridge as parent interface

If the operator already runs a downstream switch off their MikroTik and wants every customer plugged into any LAN port to use the same service, they create a bridge on the router and pick that bridge as the parent interface. See the bridge-as-parent guide for the full operator workflow. The parent-interface dropdown groups options by type (Bridges, Ethernet, SFP, VLAN). Bridges are filtered to exclude bridge, bridge-lan, fyberpay-tunnel, and any FyberPay-managed br-svc-* bridge (those are reserved by the reconciler itself). VLAN-on-bridge is allowed for tagged trunks.

Reserved interfaces (safety guard)

Before any RouterOS write, the reconciler checks the parent interface against a reserved set computed live from the router. The reserved set is the union of seven sources:
  1. Always-reserved names: bridge, bridge-lan, fyberpay-tunnel
  2. Members of bridge-lan (the management LAN)
  3. Interfaces with a bound DHCP client (the WAN uplink)
  4. Interfaces a default route exits through
  5. Members of the RouterOS WAN interface-list, if the operator set one
  6. PPPoE/L2TP/SSTP client interfaces (the router dialing out to its upstream)
  7. FyberPay-managed service-scoped bridges (br-svc-*) — identified by their service-tag comment
Any service create / update / reconcile that targets a reserved interface is rejected with a 400 before any router write happens. This prevents the entire class of “FyberPay accidentally bound a customer service to my management LAN” bugs.

Drift detection

A BullMQ background job runs every ~15 minutes per device. For each NasService, it computes the diff between the live router state and the desired state. If the diff is non-empty, the service is marked degraded and an outbox event (nas.service.drift_detected) is emitted. Drift detection is detect-only by default. The operator clicks Reconcile on the service card to apply the diff. Auto-healing is intentionally not on by default to avoid silently undoing deliberate operator changes made in Winbox.

Reconfigure semantics (hard cut)

When an operator changes a service’s type, parentInterface, or vlanId, the reconciler tears down the old resources and creates new ones. Active customer sessions on the affected service are kicked. The UI surfaces a confirmation dialog quoting the impact (“This will disconnect N active users. Re-issue with confirm=true to proceed.”) before allowing the change. Non-disruptive changes (subnet/gateway/pool tweaks, walled-garden adjustments) apply without kicking sessions.

Other writes

Domains: PUT /rest/ip/hotspot/walled-garden IPs: PUT /rest/ip/hotspot/walled-garden/ipEach hotspot service maintains its own walled-garden rules (Safaricom Daraja endpoints, FyberPay’s payment callback domain, M-Pesa portal). Operators can add custom entries per service.
Add entry: PUT /rest/ip/firewall/address-list Remove entry: DELETE /rest/ip/firewall/address-list/{id}Used for walled-garden enforcement on the L3 path (post-dunning subscribers redirected to a “pay your bill” portal until they pay).
Endpoint: PATCH /rest/queue/simple/{id}Optional. Used when an ISP manages bandwidth through router-side queues rather than RADIUS attributes (the recommended path is RADIUS-driven via FreeRADIUS, see the FreeRADIUS integration).
Endpoint: POST /rest/system/rebootTriggers a remote reboot. Requires admin or super_admin role. All reboot actions are recorded in the audit log.

What FyberPay does NOT manage on the router

  • WAN configuration: never touched. WAN is detected (sources 3/4/5/6 of the reserved set) and protected.
  • Operator-managed bridges: their existence and port membership are owned by the operator. FyberPay binds to bridges but never modifies their members or comments.
  • Default firewall: never touched. The bootstrap script only adds tunnel-traffic allow rules.
  • Existing PPP profiles: never touched. FyberPay creates per-service profiles named ppp-prof-svc-<slug>.
This separation is deliberate. The operator can edit anything in Winbox without breaking FyberPay, and the drift detector will surface any divergence rather than silently overwriting the operator’s intent.

Fleet Monitoring

FyberPay polls all configured NAS devices in parallel (batches of 10) to build the fleet status dashboard. Each device reports:
  • Reachability (online/offline)
  • Board name and RouterOS version
  • CPU load percentage
  • Memory usage percentage
  • System uptime
  • Active PPP session count
Devices without RouterOS API credentials configured appear as “unreachable” with an explicit error message.

RADIUS Configuration

The bootstrap script configures each router as a RADIUS client pointing to FyberPay’s FreeRADIUS server:
/radius add \
    service=ppp \
    address=10.99.0.1 \
    secret="<shared-secret>" \
    authentication-port=1812 \
    accounting-port=1813 \
    timeout=3s \
    comment="FyberPay RADIUS"

/ppp aaa set use-radius=yes accounting=yes interim-update=5m
/radius incoming set accept=yes port=3799
The interim-update=5m setting tells the router to send RADIUS accounting updates every 5 minutes. This is required for accurate bandwidth tracking and session monitoring in FyberPay.

Troubleshooting

  1. Verify the SSTP tunnel is established: check /interface sstp-client print on the router
  2. Confirm the tunnel has an IP in the 10.99.x.x range: /ip address print where interface=fyberpay-tunnel
  3. Ensure the www service is enabled and bound to the tunnel subnet: /ip service print
  4. Check that the firewall allows tunnel traffic: /ip firewall filter print where comment~"FyberPay"
The NAS device record in FyberPay is missing the RouterOS API username or password. Re-run the bootstrap script or manually update the device credentials in Settings > Network > NAS Devices.
  • Confirm the tunnel uses profile=fyberpay-tunnel (not profile=default)
  • Check that verify-server-certificate=no is set (FyberPay uses self-signed certs for the SSTP server)
  • Verify the router has stable internet connectivity: /ping 8.8.8.8 count=5
  • Review tunnel logs: /log print where topics~"sstp"
  • Verify the fyberpay-api user exists: /user print where name=fyberpay-api
  • Check the user group has api and rest-api policies: /user group print where name=fyberpay-api
  • Confirm the password matches what is stored in FyberPay (re-run bootstrap if unsure)
FyberPay wraps all RouterOS API calls in a circuit breaker. If a router is consistently unreachable (multiple consecutive failures), the circuit breaker opens and stops sending requests for a cooldown period. The device will show as unreachable until the circuit closes and the next health check succeeds.
The reconciler hit a RouterOS write error mid-flight. Click Reconcile on the service card to retry. If it stays pending, common causes:
  • Parent interface no longer exists (renamed or deleted in Winbox)
  • Parent interface has its own IP that conflicts with the service’s allocated subnet
  • A bridge member port has its own /ip/address (RouterOS won’t allow it as a bridge port)
  • The router is unreachable (circuit breaker open)
The Diagnostics panel on the device page shows the specific RouterOS error from the last reconcile attempt.
Drift detection found a difference between the live router state and the desired state. Common causes:
  • An operator manually deleted the PPPoE/hotspot server in Winbox
  • The router was reset to defaults but FyberPay’s NasService row still exists
  • Someone modified a FyberPay-managed resource without going through the FyberPay UI
Click Reconcile on the service card to re-apply the desired state. If the operator change was intentional (they wanted the resource gone), delete the NasService in FyberPay instead.
Possible causes:
  • The bridge is disabled. Run /interface/bridge enable <name> on the router.
  • The bridge name is bridge, bridge-lan, or fyberpay-tunnel (always-reserved).
  • The bridge’s comment carries a FyberPay service tag (FyberPay-svc:...). Either you accidentally edited an existing br-svc-* bridge’s comment, or this is a FyberPay-managed bridge. Pick a different bridge with a different name.
  • The router is unreachable, so FyberPay cannot list its interfaces.
See the bridge-as-parent troubleshooting for more.

Security Considerations

  • All API traffic flows through the encrypted SSTP tunnel. No RouterOS API ports are exposed on public interfaces.
  • API credentials are encrypted at rest using AES-256 (the platform ENCRYPTION_KEY).
  • The fyberpay-api user group has minimal permissions: no access to policy, password, sensitive, or sniff operations.
  • Every write operation (reboot, queue change, address list modification) is recorded in FyberPay’s audit log with the acting user, timestamp, and IP address.