No description
Find a file
2026-10-19 09:50:18 -04:00
.gitignore .gitignore 2026-10-19 09:50:18 -04:00
LICENSE *: initial commit 2026-10-19 09:49:51 -04:00
README.md *: initial commit 2026-10-19 09:49:51 -04:00
tpi06.py *: initial commit 2026-10-19 09:49:51 -04:00

tpi06

A small Python client and CLI for the local web API of the TRENDnet TPI-06 6-outlet managed PDU, plus notes on the API itself.

TRENDnet does not document this API. It is the same JSON API the device's web admin UI uses. Everything here was reverse-engineered from a browser capture and the UI's JavaScript bundle on firmware 1.1.0.27. A firmware update can change or break any of it.

Status

Area State
Login / bearer token auth Confirmed
Outlet on/off Confirmed
Outlet reboot Confirmed
Status reads (switchview, dashboard, outlet config) Confirmed
Token refresh, logout Endpoint known from the UI source, request shape inferred, not yet captured
Everything else in the route table Endpoint and method from the UI source only. Payloads unknown.

Requirements

  • Python 3.8+
  • requests
pip install requests

Quick start

export TPI06_HOST=192.168.0.80
export TPI06_USER=admin
export TPI06_PASS='...'

./tpi06.py status          # table of outlets: name, on/off, W, A
./tpi06.py off 4           # turn outlet 4 off
./tpi06.py on 4            # turn outlet 4 on
./tpi06.py reboot 4        # power-cycle outlet 4
./tpi06.py raw GET /outlet/config/general
./tpi06.py raw PUT /some/path '{"json":"body"}'

raw paths are relative to /api.

As a library:

from tpi06 import TPI06

with TPI06("192.168.0.80", "admin", "secret") as pdu:   # logs in, logs out on exit
    for n, o in pdu.outlets().items():
        print(n, o["name"], o["on"], o["watts"])
    pdu.reboot_outlet(4)

TLS

The device serves HTTPS with a self-signed certificate. The client disables verification by default. To pin the certificate, export it and pass the path:

TPI06(host, user, pw, verify="/path/to/tpi06.pem")

Cloud mode

According to TRENDnet's user guide, when the unit is registered with TRENDnet Hive, all configuration is locked to the cloud. Leave cloud mode disabled if you want to manage the unit locally through this API.

API reference

Base URL: https://<device>/api

Conventions

  • Auth: every request carries Authorization: bearer <token>. Unauthenticated calls from the UI send the header with an empty token (bearer ).

  • Request bodies: JSON, but the UI sends them with Content-Type: text/plain;charset=UTF-8. The client copies this in case the server checks it.

  • Responses: JSON. Every response observed includes this envelope:

    { "errCode": 0, "message": "OK", "status": "0", "msg": "success" }
    

    errCode: 0 means success. The client raises TPI06Error for any other value.

  • Numbers as strings: many readings come back as padded strings, e.g. "outlet1_power": " 68.9". Parse them with float().

  • Server: lighttpd 1.4.54. The X-Rate-Limit: 5000 response header is present, but its meaning is unknown.

Authentication

POST /sys/login

The UI sends an empty bearer token on this request.

{ "userLogin": { "usr": "admin", "pwd": "<password>" } }

Response:

{
  "token": "<JWT>",
  "first_login": false,
  "timeout": 3600,
  "errCode": 0, "message": "OK", "status": "0", "msg": "success"
}
  • timeout is the session lifetime in seconds.
  • The JWT is HS256. Its iat and exp claims are the device's uptime in seconds, not Unix time, so don't compare them to the wall clock. Use timeout instead.

GET /sys/token_refresh

The UI calls this at 80% of timeout with the current token and replaces its stored token with token from the response. The response also carries a fresh timeout.

POST /sys/logout

Ends the session.

Outlet control (confirmed)

Outlet IDs are 1–6. The always-on bypass outlet cannot be controlled.

PUT /overview/outlet/enable

Turn an outlet on or off.

{ "outletEnConfs": { "outlet_id": 4, "outlet_enable": 0 } }

outlet_enable: 0 = off, 1 = on.

The change is not instant. Each outlet's configured power-on and power-off delay (/outlet/config/general) applies. In the capture, outlet 4 had a 4 s delay, and switchview reported the new state about 4 s after the request. If you poll to confirm a change, wait at least that long.

PUT /overview/outlet/reboot

Power-cycle one outlet.

{ "outletRBConfs": { "outlet_id": 4 } }

While the outlet is cycling, outlet_N_switch_enable in /outlet/config/outletswitchenable goes false. This appears to be the UI's "toggle locked" flag, not the power state.

The UI's Power Cycle button cycles all outlets. Its payload has not been captured. It probably uses this endpoint with a sentinel outlet_id, but that is untested. Do not guess at it on a PDU that is powering anything you care about.

Status reads (confirmed)

GET /dashboard/switchview

Per-outlet live state. Response object switchOutletStatus, with these keys repeated for N = 1–6:

Key Example Meaning
outletN_id 4 Outlet number
outletN_name "outlet4" User-assigned name
outletN_enable true Current power state
outletN_isconnected false Unclear. It was false on outlets drawing 60–90 W.
outletN_power " 68.9" Watts
outletN_voltage " 120" Volts
outletN_current " 0.6" Amps
outletN_powrb_btn_en true Reboot button enabled in the UI

The object also has one top-level key, outlet_power_reboot_en (bool).

GET /dashboard/agent

System overview. Response objects:

  • dashSwitchInfo: uptime (human-readable string), fw_version
  • dashSystemStatus: voltage, total_current, frequency, temperature. The temperature string includes the unit, e.g. "107.6 ℉".
  • dashAdminInfo: system_name, system_location, system_contact, serial_no
  • dashEtherInfo: IPv4 and IPv6 addressing, DHCP flags, MAC
  • dashPowerConsumption: total_max_watts, total_used_watts, total_available_watts, out1_watts … out6_watts

GET /sys/top_banner

Header-bar data. Fields include user_id, device_model, device_name, location_name, fw_version, devCurrentTime, max_safe_vol, min_safe_vol, max_temp, cloud_mode, cloud_online_status, language_type, and system message slots message1…message5.

This endpoint answered with an empty bearer token. See Security notes.

GET /outlet/config/outletswitchenable

outletswitchenableConfs.outlet_N_switch_enable (bool, N = 1–6). This appears to be whether each outlet's toggle is usable, and it goes false during a reboot. It is not the power state; use switchview for that.

GET /outlet/config/general

outletGenConfs, with these keys for each outlet N:

  • outlet_N_id
  • outlet_N_name
  • outlet_N_pow_del_en: power-delay enabled
  • outlet_N_pow_on_del: power-on delay, seconds
  • outlet_N_pow_off_del: power-off delay, seconds

There is also a global outlet_pow_del_en.

GET /outlet/config/safe

outletSafeConfs: outlet_safe_max_vol, outlet_safe_min_vol, and outlet_safe_vol_en (default range 95–130 V).

GET /outlet/config/remoterebootdelay

remoterebootdelayConfs.outlet_N_remote_reboot_delay (integer, N = 1–6).

Full route table

The UI source (apiURL map in the JS bundle) lists the routes below. ✅ means the route was exercised in a capture. Everything else is the method and path only. Request payloads are unknown for any write without ✅. To learn a payload, perform the action in the web UI with the browser's network tab open.

Write routes are marked ⚠️ where a wrong payload or a misfire could knock the device or its loads offline.

Session and system messages

Method Path Purpose
POST /sys/login Log in, get token ✅
POST /sys/logout Log out
GET /sys/token_refresh Renew token
GET /sys/top_banner Header-bar info ✅
POST /sys/confirm_message Clear or ack a system message

Dashboard and outlet control

Method Path Purpose
GET /dashboard/agent System overview ✅
GET /dashboard/switchview Per-outlet state and power ✅
PUT /overview/outlet/enable Outlet on/off ✅
PUT /overview/outlet/reboot Power-cycle outlet ✅

Outlet configuration

Method Path Purpose
GET /outlet/config/outletswitchenable Per-outlet toggle-enabled flags ✅
GET /outlet/config/general Names and power on/off delays ✅
PUT /outlet/config/general Set names and delays
GET /outlet/config/safe Safe-voltage range ✅
PUT /outlet/config/safe Set safe-voltage range
GET /outlet/config/remoterebootdelay Remote reboot delay ✅
PUT /outlet/config/remoterebootdelay Set remote reboot delay

Schedules

Method Path Purpose
GET /outlet/schedule/config List schedule profiles
POST /outlet/schedule/config Add schedule profile
PUT /outlet/schedule/config Modify schedule profile
DELETE /outlet/schedule/config Delete schedule profile
PUT /outlet/schedule/enable Enable/disable a schedule

Ping auto-reboot (watchdog)

Method Path Purpose
POST /tools/confirm_IPSite Test whether a host or IP answers a ping
POST /outlet/ping_reboot/pinghostsetting Add a ping host
DELETE /outlet/ping_reboot/pinghostsetting Delete a ping host
GET /outlet/ping_reboot/outletrebootsetting Get per-outlet watchdog rules
PUT /outlet/ping_reboot/outletrebootsetting Set per-outlet watchdog rules ⚠️
PUT /outlet/ping_reboot/outletpingenable Enable/disable watchdog for an outlet ⚠️
PUT /outlet/ping_reboot/outletpingenableall Enable/disable watchdog for all outlets ⚠️

Network, system, time

Method Path Purpose
GET /ethernet/info IPv4 settings
PUT /ethernet/info Set IPv4 settings ⚠️
GET /sys/sys_setting Device name, location, contact, account
PUT /sys/sys_setting Set the above (includes username/password change) ⚠️
PUT /sys/confirm_password Verify current password
GET /sys/https_enable HTTPS state
PUT /sys/check_httpsport Check whether an HTTPS port is in use
GET /sys/time_date_setting Time, date, time zone
PUT /sys/time_date_setting Set time, date, time zone
GET /sys/cloud_setting TRENDnet Hive settings
PUT /sys/cloud_setting Enable/disable Hive (locks local config when enabled) ⚠️

Logging and alerts

Method Path Purpose
GET /sys/log Remote log server settings and log entries
GET /sys/email_alert Email alert settings
PUT /sys/email_alert Set email alert settings
POST /sys/send_test_mail Send a test email

Maintenance

Method Path Purpose
POST /sys/config_backup Download configuration
POST /sys/config_restore Upload configuration ⚠️
POST /sys/reboot Reboot the PDU controller ⚠️
POST /sys/factory_reset Factory reset ⚠️
POST /sys/firmware/check Upload and validate a firmware image ⚠️
POST /sys/firmware/do_upgrade_manual Apply uploaded firmware ⚠️

It is not yet confirmed whether /sys/reboot drops power to the outlets or only restarts the controller. Assume it may drop power until tested on a unit with nothing important plugged in.

Security notes

  • Unauthenticated reads. /sys/top_banner returns the admin username, model, and firmware version with no token. Whether other GET routes also skip auth has not been tested. To check from the management network:

    curl -sk -H 'Authorization: bearer' https://<device>/api/dashboard/switchview
    

    If that returns outlet data, anyone who can reach the device can read it.

  • Isolate the device. Put the PDU on a management VLAN or otherwise firewall it. Defaults out of the box are admin / admin at 192.168.10.80.

  • HAR captures contain secrets. A browser capture of the login includes the admin password in cleartext and a live session token. Treat HAR files from this device as credentials: don't commit them, and rotate the password if one has been shared.

  • Credentials in this client come from environment variables. Don't hard-code them.

Firmware compatibility

Firmware Status
1.1.0.27 Routes and payloads above were captured on this version
Newer Untested

After a firmware upgrade, re-check before relying on the client:

  1. Load the web UI and save the main *.bundle.min.js.
  2. Search it for apiURL and diff the route map against the table above.
  3. Re-capture one on/off and one reboot to confirm the payload shapes.

Contributing findings

The highest-value gaps, in order:

  1. The Power Cycle (all outlets) payload.
  2. The PUT /outlet/config/general payload, so outlet names and delays can be set.
  3. Schedule and ping-watchdog payloads.
  4. Which GET routes skip auth.
  5. Whether /sys/reboot interrupts outlet power.

Capture each one by performing the action in the UI with the network tab open. Then redact the Authorization header and any pwd fields before sharing.

License and disclaimer

This is not affiliated with or endorsed by TRENDnet. Use at your own risk: this tool switches mains power to real equipment.

See LICENSE