LIVE v2.1.0 EPON + GPON API only — no frontend

One REST layer for every OLT you run.

Test token (X-API-Token):

Read OLT health, pull per-PON statistics, and push ONU configuration — description and VLAN — across BDCOM, VSOL and Solitine first, with Huawei MA and ZTE C3xx built in. CLI, SNMP or NETCONF underneath; identical JSON on top.

5 vendor drivers
2 PON types per vendor
10 documented endpoints
0 hardcoded credentials
Coverage

Supported vendors

Initial support per the project brief covers BDCOM, VSOL and Solitine — both EPON and GPON. Huawei MA series and ZTE C3xx ship in the same box.

simInitial · EPON+GPON

BDCOM

P3310C and E-PON / G-PON units
CLI/SSHSNMP
simInitial · EPON+GPON

VSOL

V1600D series
TelnetSSHSNMP
simInitial · EPON+GPON

Solitine

SOLT series
TelnetSSHSNMP
simExtended · GPON

Huawei MA

MA5600T, MA5800 series
CLI/SSHNETCONFSNMP
simExtended · GPON

ZTE C3xx

C320 and C3xx series
CLI/SSHSNMP
Mandatory first step — register device credentials REQUIRED

These credentials are mandatory to add for every vendor you want to reach live. The client provides the values (management IP, CLI username and password). Until a vendor is registered below, all its endpoints run in simulation mode — responses are generated, no device is touched. Passwords are stored server-side (file permission 0600) and are never returned by any GET endpoint.

cURL — register BDCOM (repeat per vendor)
# MANDATORY — without this the vendor stays in simulation mode
curl -X POST __API_BASE__/api/v1/devices/bdcom/credentials \
  -H 'Content-Type: application/json' \
  -d '{
        "host": "10.0.0.11",          # OLT management IP (required)
        "port": 22,                    # 22 SSH / 23 Telnet (optional)
        "protocol": "ssh",             # ssh | telnet (optional)
        "username": "client_user",     # CLI user (required)
        "password": "client_pass",     # CLI pass (required)
        "snmp_community": "public",    # optional
        "pon_types": ["EPON","GPON"],  # optional
        "live_mode": true              # false = simulate only
      }'

The same body works for vsol, solitine, huawei and zte — just change the vendor in the URL. Check what is configured any time with GET /api/v1/devices, verify reachability with POST /api/v1/devices/{vendor}/test, and remove credentials with DELETE /api/v1/devices/{vendor}/credentials.

Interface

Endpoints

Three core operations, one consistent schema for every vendor: overall OLT health, per-PON statistics, and ONU status with description / VLAN updates.

MethodPathDescription
POST/api/v1/devices/{vendor}/credentialsMandatory first. Register host / username / password for a vendor. Enables live mode.
GET/api/v1/devicesCredential configuration status per vendor — live vs simulation, source, required fields.
POST/api/v1/devices/{vendor}/testTCP reachability test against the registered host:port.
DELETE/api/v1/devices/{vendor}/credentialsRemove stored credentials; vendor falls back to simulation.
PATCH/api/v1/devices/live-modeToggle live CLI execution globally: {"live_mode": true}.
GET/healthService health, version, live-mode flag.
GET/olts/{vendor}Operation 1 — overall health: status, uptime, temperature, CPU, memory, firmware, PON types.
GET/pons/{vendor}Operation 2 — per-PON statistics: type (EPON/GPON), status, ONU count, RX/TX power, errors, distance.
GET/onus/{vendor}[/{onu_id}]Operation 3a — ONU status details. Optional filters: ?pon_id=1, ?status=online.
PUT PATCH/onus/{vendor}/{onu_id}Operation 3b — push config: {"description": "...", "vlan": 1-4094}. PUT = full, PATCH = partial. Returns the exact CLI plan.
Testing environment

Live API tester

Fire real requests against this deployment and inspect the JSON — no setup needed. Requests run from your browser against the same origin.

READY
Pick an endpoint and press Send request. Try GET /pons/bdcom or PUT /onus/bdcom/1 to see a config push in simulation mode.
Sample data

Response samples

Exactly what each call returns in simulation mode — the same shape you will get against real devices once credentials are registered.

GET /olts/bdcomOperation 1
{
  "vendor": "bdcom",
  "status": "online",
  "mode": "simulation",
  "model": "P3310C",
  "uptime": "540h 15m",
  "temperature": 41.0,
  "cpu_usage": 8.0,
  "memory_usage": 38.0,
  "firmware_version": "V2.1.4",
  "protocols": ["CLI/SSH", "SNMP"],
  "pon_types": ["EPON", "GPON"],
  "last_seen": "2026-09-03T19:40:00+06:00"
}
GET /pons/bdcomOperation 2
[
  {
    "vendor": "bdcom",
    "pon_id": 1, "pon_type": "EPON",
    "status": "active",
    "onu_count": 16,
    "rx_power": -15.3, "tx_power": -5.2,
    "error_count": 0,
    "distance_km": 12.5
  },
  {
    "vendor": "bdcom",
    "pon_id": 2, "pon_type": "GPON",
    "status": "active",
    "onu_count": 8,
    "rx_power": -16.8, "tx_power": -4.9,
    "error_count": 2,
    "distance_km": 9.8
  }
]
PUT /onus/bdcom/1Operation 3b
{
  "onu": {
    "vendor": "bdcom", "onu_id": 1,
    "pon_id": 1,
    "serial": "BDC0M1A10001",
    "status": "online",
    "description": "Living Room ONT",
    "vlan": 100,
    "rx_power": -21.2, "tx_power": -9.8,
    "uptime": "120h 10m"
  },
  "updated": {"description": true, "vlan": true},
  "push": {
    "mode": "simulation",
    "commands": [
      "ont description 1 'Living Room ONT'",
      "ont vlan 1 100",
      "write memory"
    ],
    "persist": "write memory",
    "executed": false,
    "detail": "simulation mode — no credentials
configured; CLI plan generated, device untouched"
  }
}
Use it from anywhere

Guides in different languages

The same flow in five languages: read health, list PONs, list ONUs, push a description + VLAN update. The API is plain JSON over HTTP — any language with an HTTP client works.

bash
# 0. MANDATORY — register credentials (once per vendor)
curl -X POST __API_BASE__/api/v1/devices/bdcom/credentials \
  -H 'Content-Type: application/json' \
  -d '{"host":"10.0.0.11","username":"client_user","password":"client_pass","live_mode":false}'

# 1. Overall health
curl -s __API_BASE__/olts/bdcom

# 2. Per-PON statistics
curl -s __API_BASE__/pons/bdcom

# 3. ONU status
curl -s __API_BASE__/onus/bdcom

# 4. Push config — description + VLAN
curl -s -X PUT __API_BASE__/onus/bdcom/1 \
  -H 'Content-Type: application/json' \
  -d '{"description":"Living Room ONT","vlan":100}'
python — pip install requests
import requests

BASE = "__API_BASE__"

# 0. MANDATORY — register credentials (once per vendor)
requests.post(f"{BASE}/api/v1/devices/bdcom/credentials", json={
    "host": "10.0.0.11", "username": "client_user",
    "password": "client_pass", "live_mode": False,
}).raise_for_status()

# 1. Overall health
health = requests.get(f"{BASE}/olts/bdcom").json()
print(health["status"], health["model"])

# 2. Per-PON statistics
pons = requests.get(f"{BASE}/pons/bdcom").json()
for p in pons:
    print(p["pon_id"], p["pon_type"], p["onu_count"])

# 3. ONU status
onus = requests.get(f"{BASE}/onus/bdcom").json()

# 4. Push config — description + VLAN
r = requests.put(f"{BASE}/onus/bdcom/1",
                 json={"description": "Living Room ONT", "vlan": 100}).json()
print(r["updated"], r["push"]["commands"])
javascript — node 18+ / browser fetch
const BASE = "__API_BASE__";

// 0. MANDATORY — register credentials (once per vendor)
await fetch(`${BASE}/api/v1/devices/bdcom/credentials`, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ host: "10.0.0.11", username: "client_user",
                         password: "client_pass", live_mode: false }),
});

// 1. Overall health
const health = await (await fetch(`${BASE}/olts/bdcom`)).json();

// 2. Per-PON statistics
const pons = await (await fetch(`${BASE}/pons/bdcom`)).json();

// 3. ONU status
const onus = await (await fetch(`${BASE}/onus/bdcom`)).json();

// 4. Push config — description + VLAN
const res = await fetch(`${BASE}/onus/bdcom/1`, {
  method: "PUT",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ description: "Living Room ONT", vlan: 100 }),
});
const out = await res.json();
console.log(out.updated, out.push.commands);
go — net/http
package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "net/http"
    "io"
)

func post(url string, body any) {
    b, _ := json.Marshal(body)
    resp, err := http.Post(url, "application/json", bytes.NewReader(b))
    if err != nil { panic(err) }
    defer resp.Body.Close()
    out, _ := io.ReadAll(resp.Body)
    fmt.Println(resp.Status, string(out))
}

func main() {
    base := "__API_BASE__"

    // 0. MANDATORY — register credentials
    post(base+"/api/v1/devices/bdcom/credentials", map[string]any{
        "host": "10.0.0.11", "username": "client_user",
        "password": "client_pass", "live_mode": false,
    })

    // 1–3. GET endpoints
    for, path := range []string{"/olts/bdcom", "/pons/bdcom", "/onus/bdcom"} {
        resp, _ := http.Get(base + path)
        out, _ := io.ReadAll(resp.Body)
        resp.Body.Close()
        fmt.Println(path, string(out))
    }

    // 4. Push config
    post(base+"/onus/bdcom/1", map[string]any{
        "description": "Living Room ONT", "vlan": 100,
    })
}
php — curl extension
<?php
$BASE = "__API_BASE__";

function call($method, $path, $body = null) {
  global $BASE;
  $ch = curl_init($BASE . $path);
  curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => $method,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER      => ["Content-Type: application/json"],
    CURLOPT_POSTFIELDS      => $body ? json_encode($body) : null,
  ]);
  return json_decode(curl_exec($ch), true);
}

// 0. MANDATORY — register credentials
call("POST", "/api/v1/devices/bdcom/credentials", [
  "host" => "10.0.0.11", "username" => "client_user",
  "password" => "client_pass", "live_mode" => false,
]);

// 1–3. Reads
$health = call("GET", "/olts/bdcom");
$pons   = call("GET", "/pons/bdcom");
$onus   = call("GET", "/onus/bdcom");

// 4. Push config — description + VLAN
$out = call("PUT", "/onus/bdcom/1", [
  "description" => "Living Room ONT", "vlan" => 100,
]);
print_r($out["updated"]);
Contract

Canonical schemas

Every vendor driver maps its native CLI/SNMP/NETCONF output onto these three shapes — your integration code never changes when a new vendor is added.

OLTHealth
statusenum
REQUIRED online | degraded | offline
vendorstring
bdcom · vsol · solitine · huawei · zte
modeenum
live | simulation
model · uptimestring
device identity, uptime string
temperaturenumber
CPU temperature, °C
cpu_usage · memory_usagenumber
percent 0–100
firmware_versionstring
device firmware
pon_typesarray
subset of EPON, GPON
PONStat
pon_idint 1–128
REQUIRED PON port identifier
pon_typeenum
REQUIRED EPON | GPON
statusenum
REQUIRED active | idle | alarm | fault
onu_countint
registered ONUs on the port
rx_power · tx_powernumber
optical power, dBm
error_countint
port error counter
distance_kmnumber
distance to furthest ONU
ONUStatus
onu_idint 1–256
REQUIRED ONU identifier
statusenum
REQUIRED online | offline | degraded | unknown
descriptionstring ≤128
writable via PUT / PATCH
vlanint 1–4094
writable via PUT / PATCH
pon_idint
parent PON port
serialstring
ONU serial / MAC
rx_power · tx_powernumber
optical power, dBm
uptimestring
ONU online time
Deployment

Installation guide

Four steps from zero to a running API — locally or on any Linux server. Python 3.11+ required.

Get the source

Clone the private repository or unpack the delivery package.

git clone git@github.com:dotprogrammers/olt-api.git
cd olt-api

Create environment

Isolated Python venv with pinned dependencies.

python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt

Register credentials

No .env editing needed — POST the client's test credentials to the credentials API, or set VENDOR_HOST / VENDOR_USER / VENDOR_PASS variables.

curl -X POST localhost:8000/api/v1/devices/bdcom/credentials \
  -H 'Content-Type: application/json' \
  -d '{"host":"10.0.0.11","username":"u","password":"p"}'

Run the server

Uvicorn for dev; systemd for production. Docs auto-mounted.

uvicorn main:app --host 0.0.0.0 --port 8000
# Swagger UI  → /docs
# Docs hub    → /
# ReDoc       → /redoc

Production reference on this server: systemd unit olt-api-vendor.service behind nginx — source at /var/www/olt-api-project/, credentials store at device_credentials.json (0600).

Copied to clipboard