User Tools

Site Tools


products:software:edgeos:api

EdgeOS API Guide

The EdgeOS API is not publicly documented. However as the requests and responses can be monitored in a web-browser along with the JavaScript source being available, a lot of information on how it works can be derived.

A subset of the information here was taken from https://github.com/matthew1471/EdgeOS-API/tree/master/Documentation

Authentication

A HTTP POST to https://host-or-ip/ with the username and password encoded as a simple application/x-www-form-urlencoded form with the following request content will grant you a PHPSESSID cookie that is used to confirm you are authenticated:

username=<<USERNAME>>&password=<<PASSWORD>>

This will return a HTTP status code "303 See Other" on success and the same login form again with a "200 OK" containing the text "The username or password you entered is incorrect" on failure, be careful as some web clients will automatically follow the 303 redirection and the cookies may not be where you expect them to be.

The session ID is returned multiple times but the only header of importance for authentication is:

Set-Cookie: PHPSESSID=9a00126c5bf04e29835f7c13fe5ab155; secure

A session is valid for 15 minutes and is refreshed on every web request.

A session can be extended with a HTTP GET to /api/edge/heartbeat.json?t=«EPOCH» where «EPOCH» is the current time in EPOCH notation (such as "1591537772865").

REST API

Get Configuration

A HTTP GET to /api/edge/get.json can be used to get a JSON formatted dictionary containing the configuration (and the current SESSION_ID).

Get Configured Sections

A HTTP GET to /api/edge/getcfg.json can be used to get a JSON formatted list stating which sections have been modified.

Data

The /api/edge/data.json endpoint can query a variety of stats and data.


DHCP Leases

A HTTP GET to /api/edge/data.json?data=dhcp_leases can be used to get a JSON formatted list of DHCP leases:

{"success": "1", "output": {"dhcp-server-leases": {"LAN2": "", "LAN1": {"192.168.0.180": {"expiration": "2020/06/08 13:07:17", "pool": "LAN1", "mac": "xx:xx:xx:xx:xx:xx", "client-hostname": "Versa"}, "192.168.0.165": {"expiration": "2020/06/08 08:42:42", "pool": "LAN1", "mac": "xx:xx:xx:xx:xx:xx", "client-hostname": ""}, "192.168.0.104": {"expiration": "2020/06/07 16:19:20", "pool": "LAN1", "mac": "xx:xx:xx:xx:xx:xx", "client-hostname": "andys-6s"}}}}}


DHCP Stats

A HTTP GET to /api/edge/data.json?data=dhcp_stats can be used to get a JSON formatted list of DHCP stats:

{"success": "1", "output": {"dhcp-server-stats": {"LAN2": {"pool_size": "253", "leased": "0", "available": "253"}, "LAN1": {"pool_size": "253", "leased": "3", "available": "250"}}}}


System Information

A HTTP GET to /api/edge/data.json?data=sys_info obtains basic system information:

{"success": "1", "output": {"sw_ver": "EdgeRouter.ER-e300.v2.0.9-beta.3.5296219.200507.1538", "unms": {"daemon": "Not running", "status": "", "last": ""}, "fw-latest": {"version": "v2.0.8-hotfix.1", "url": "https://fw-download.ubnt.com/data/e300/669e-edgerouter-2.0.8-hotfix.1-752ed9f0476a4cb3adcce84ec537b228.tar", "md5": "d4b30e3821621f16f6e960d753eaf073", "state": "up-to-date"}}}


Routes

A HTTP GET to /api/edge/data.json?data=routes obtains route information:

{"success": "1", "output": [{"pfx": "0.0.0.0/0", "nh": [{"t": "S>*", "metric": "210/0", "via": "xxx.xxx.xxx.xxx", "intf": "eth0"}]}, {"pfx": "xxx.xxx.xxx.xxx/21", "nh": [{"t": "C>*", "intf": "eth0"}]}, {"pfx": "127.0.0.0/8", "nh": [{"t": "C>*", "intf": "lo"}]}, {"pfx": "192.168.0.0/24", "nh": [{"t": "C>*", "intf": "eth1"}]}]}


Default Configuration Status

A HTTP GET to /api/edge/data.json?data=default_config obtains information on whether the device is operating with no user supplied configuration:

{"success": "1", "output": {"is_default": "0"}}


Download Configuration

To download the configuration send a HTTP GET to /api/edge/config/save.json:

{"CONFIG": {"success": "1", "path": "/tmp/sysd-save.ycYPpL"}, "success": true}

and then make a request to /files/config/. The file will be deleted once the request has been made.

Operations


Reboot

The device can be rebooted by sending a HTTP POST to /api/edge/operation/reboot.json

Reset Default Configuration

The device configuration can be reset by sending a HTTP POST to /api/edge/operation/reset-default-config.json

Shutdown

The device can be shutdown by sending a HTTP POST to /api/edge/operation/shutdown.json

Support File

A support file can be generated by sending a HTTP POST to /api/edge/operation/get-support-file.json

Renew DHCP

The DHCP lease can be renewed by sending a HTTP POST to /api/edge/operation/renew-dhcp.json

Release DHCP

The DHCP lease can be released by sending a HTTP POST to /api/edge/operation/release-dhcp.json

Clear Traffic Analysis

The Traffic Analysis data can be cleared by sending a HTTP POST to /api/edge/operation/clear-traffic-analysis.json

Check For Firmware Updates

A check for firmware updates can be performed by sending a HTTP POST to /api/edge/operation/refresh-fw-latest-status.json

Updates


Batch Updates

The /api/edge/batch.json endpoint allows you to make batch updates to the device's configuration.

POST /api/edge/batch.json

{
    "SET":{"system":{"host-name":"<hostname>"},"service":{"unms":{"disable":null}}},
    "GET":{"system":null,"service":null}
}

Response:

{
    "SET": {"failure": "0", "success": "1"}, 
    "SESSION_ID": "session_id", 
    "GET": {
        "system": { system as json }, 
        "service": { service as json }, 
    "COMMIT": {"failure": "0", "success": "1"}, 
    "SAVE": {"success": "1"}, 
    "success": true
}

Websocket - CLI

The CLI can be accessed from wss://host-or-ip/ws/cli. The data sent to the WebSocket will be as you would type on CLI and the received data is just the response raw.

Websocket - Stats

You can get streaming statistical data from the endpoint wss://host-or-ip/ws/stats. The data from the WebSocket is framed oddly, it's actually a streaming protocol that has been sent and received over WebSocket. The data will not arrive like you might expect. You *MUST* reassemble the web socket data fragments since the frames may not align with data boundaries. Commands must be sent with a valid SESSION_ID. Origin header is not needed for the 2.x branch of the firmware but is needed for 1.x branches.

The format of data to and from the WebSocket stream is "LENGTH\nJSON_PAYLOAD". Failure of sending properly formed messages to start the streaming will result in no messages from server aka "dead air".

When the SESSION_ID times out the WebSocket will abruptly close so it's recommended to refresh it occasionally.

249
{"SUBSCRIBE":[{"name":"export"},{"name":"discover"},{"name":"pon-stats"},{"name":"interfaces"},{"name":"system-stats"},{"name":"num-routes"},{"name":"config-change"},{"name":"users"}],"UNSUBSCRIBE":[],"SESSION_ID":"b5d5cfdb326c484abb00ca0d9effffff"}

Return values from the stream follow a similar format.

104
{
    "system-stats":
    {
        "cpu": "10",
        "uptime": "57864",
        "mem": "60"
    }
}

The webUI sends a non-standard ping every 30 seconds which consists of the following string with NO length prefix

{"CLIENT_PING"}

WebSocket Subscriptions: JSON Based

Each one of these subscriptions will output data with the response being full JSON objects:

  • system-stats: Returns cpu, memory and uptime
    {'system-stats': {'cpu': '35', 'mem': '22', 'uptime': '3321154'}}
    {'system-stats': {'cpu': '21', 'mem': '22', 'uptime': '3321157'}}
  • num-routes: Returns information about the number of active routes, use the json endpoint to fetch detailed routing information
    {'num-routes': {'connected': '5', 'static': '1', 'total': '6'}}
  • config-change: Returns only when the config has changed as an indication you need to reload
    {'config-change': {'commit': 'started'}}
    {'config-change': {'commit': 'ended'}}
  • users: Lists the users logged into the EdgeOS device including ssh, web, and vpn
  • interfaces: Shows per-interface details about the device
  • discover: Results from any devices discovered via ubnt protocols
  • export: Traffic Analysis (aka DPI) information
  • lldp-detail: Information about LLDP connected neightbors
  • udapi-statistics: System information formatted for udapi, odd dialect

WebSocket Subscriptions: RAW Console Output

Each one of these endpoints just dumps the raw console output data within a string

{'<<Request sub_id>>': '<line of text>\n' }

These are subscribed to in the same way as the JSON subscriptions above but some additional parameters may need to be specified.

Log File ("log-feed")

Basically a tail -f /var/log/messages

Firewall Statistics ("fw-stats")

Returns per-rule firewall stats:

Request:

142
{"SUBSCRIBE":[{"name":"fw-stats","sub_id":"fwstat:WAN_IN","chain":"WAN_IN"}],"UNSUBSCRIBE":[],"SESSION_ID":"9a00126c5bf04e29835f7c13fe5ab155"}
{'fwstat:WAN_IN': 'MGT_IN 10 11604461 1380173884 ACCEPT ""\n'}
{'fwstat:WAN_IN': 'MGT_IN 20 0 0 DROP "drop direct stun"\n'}
{'fwstat:WAN_IN': 'MGT_IN 30 24 1152 ACCEPT "stun"\n'}
{'fwstat:WAN_IN': 'MGT_IN 10000 8417 670074 DROP "DEFAULT ACTION"\n\n'}
{'fwstat:WAN_IN': 'WAN_IN 10 747540714 999952823643 ACCEPT "Allow established/related"\n'}
{'fwstat:WAN_IN': 'WAN_IN 20 0 0 DROP "Drop invalid state"\n'}
{'fwstat:WAN_IN': 'WAN_IN 30 1095 52610 DROP "block ET"\n'}
{'fwstat:WAN_IN': 'WAN_IN 40 0 0 DROP "block TOR"\n'}
{'fwstat:WAN_IN': 'WAN_IN 50 0 0 DROP "block EDROP"\n'}
{'fwstat:WAN_IN': 'WAN_IN 60 0 0 DROP "block China" DISABLED\n'}
{'fwstat:WAN_IN': 'WAN_IN 70 92712 5078903 ACCEPT "server - web ports - tcp"\n'}
{'fwstat:WAN_IN': 'WAN_IN 80 65556 3923195 ACCEPT "server - ssh"\n'}
{'fwstat:WAN_IN': 'WAN_IN 90 877 52516 ACCEPT "server - gitlab ssh"\n'}
{'fwstat:WAN_IN': 'WAN_IN 100 142 33791 ACCEPT "server - mosh"\n'}
{'fwstat:WAN_IN': 'WAN_IN 110 3926 143574 ACCEPT "server - unifi stun"\n'}
{'fwstat:WAN_IN': 'WAN_IN 10000 259 136357 DROP "DEFAULT ACTION"\n\n'}
{'fwstat:WAN_IN': 'WAN_LOCAL 10 55434 36097276 ACCEPT "Allow established/related"\n'}
{'fwstat:WAN_IN': 'WAN_LOCAL 20 87599 17248696 DROP "Drop invalid state"\n'}
{'fwstat:WAN_IN': 'WAN_LOCAL 61 41787 1761510 DROP "block ET"\n'}
{'fwstat:WAN_IN': 'WAN_LOCAL 62 0 0 DROP "block TOR"\n'}
{'fwstat:WAN_IN': 'WAN_LOCAL 63 100 4160 DROP "block EDROP"\n'}
{'fwstat:WAN_IN': 'WAN_LOCAL 64 0 0 DROP "block China" DISABLED\n'}
{'fwstat:WAN_IN': 'WAN_LOCAL 65 21894 1372976 ACCEPT "ICMP"\n'}
{'fwstat:WAN_IN': 'WAN_LOCAL 10000 241941 37301536 DROP "DEFAULT ACTION"\n\n'}

Port Forwarding Statistics ("pf-stats")

Contains the statistics from Port Forwarding.

NAT Statistics ("nat-stats")

Returns per-rule NAT stats:

1115
{
    "nat-stats": "1 15 DST eth0 \"Allow OpenVPN To VPN\"\n2 0 DST eth1 \"Allow OpenVPN To VPN (Hairpin)\"\n3 28 DST eth0 \"Allow qBittorrent\"\n4 0 DST eth0 \"Allow Emergency iLO (HTTP)\" DISABLED\n5 0 DST eth0 \"Allow Emergency iLO (Console)\" DISABLED\n6 7192 DST eth1 \"Redirect Google DNS To Router\"\n7 3920 DST eth1 \"Redirect Google ICMP To Router\"\n5001 46501 MASQ eth0 \"Masquerade For WAN\"\n5002 0 MASQ eth1 \"Allow OpenVPN To VPN (Hairpin)\"\n1 15 DST eth0 \"Allow OpenVPN To VPN\"\n2 0 DST eth1 \"Allow OpenVPN To VPN (Hairpin)\"\n3 28 DST eth0 \"Allow qBittorrent\"\n4 0 DST eth0 \"Allow Emergency iLO (HTTP)\" DISABLED\n5 0 DST eth0 \"Allow Emergency iLO (Console)\" DISABLED\n6 7192 DST eth1 \"Redirect Google DNS To Router\"\n7 3920 DST eth1 \"Redirect Google ICMP To Router\"\n5001 46501 MASQ eth0 \"Masquerade For WAN\"\n5002 0 MASQ eth1 \"Allow OpenVPN To VPN (Hairpin)\"\n1 15 DST eth0 \"Allow OpenVPN To VPN\"\n2 0 DST eth1 \"Allow OpenVPN To VPN (Hairpin)\"\n3 28 DST eth0 \"Allow qBittorrent\"\n4 0 DST eth0 \"Allow Emergency iLO (HTTP)\" DISABLED\n5 0 DST eth0 \"Allow Emergency iLO "
}

Ping ("ping-feed")

163
{"SUBSCRIBE":[{"name":"ping-feed","sub_id":"ping1","target":"192.168.0.1","count":"1","size":""}],"UNSUBSCRIBE":[],"SESSION_ID":"9a00126c5bf04e29835f7c13fe5ab155"}

with the response being pretty similar to a raw feed:

76
{
    "ping1": "PING 192.168.0.1 (192.168.0.1) 56(84) bytes of data.\n\n"
}

Traceroute ("traceroute-feed")

165
{"SUBSCRIBE":[{"name":"traceroute-feed","sub_id":"trace6","target":"192.168.0.254","resolve":true}],"UNSUBSCRIBE":[],"SESSION_ID":"9a00126c5bf04e29835f7c13fe5ab155"}

with the response being pretty similar to a raw feed:

98
{
    "trace6": "traceroute to 192.168.0.254 (192.168.0.254), 30 hops max, 38 byte packets\n 1"
}

Packet Capture ("packets-feed")

224
{"SUBSCRIBE":[{"name":"packets-feed","sub_id":"packets4","interface":"1","pkt_count":"1","resolve":true,"f_proto":"","f_address":"","f_port":"","f_neg":true}],"UNSUBSCRIBE":[],"SESSION_ID":"9a00126c5bf04e29835f7c13fe5ab155"}

Bandwidth Test ("bwtest-feed")

Client:

150
{"SUBSCRIBE":[{"name":"bwtest-feed","sub_id":"bandwidth5","server":"192.168.0.253"}],"UNSUBSCRIBE":[],"SESSION_ID":"9a00126c5bf04e29835f7c13fe5ab155"}

or with advanced properties set:

273
{"SUBSCRIBE":[{"name":"bwtest-feed","sub_id":"bandwidth2","server":"192.168.0.254","duration":"1","protocol":"udp","udp-bandwidth":"500","parallel-flows":"1","tcp-window-size":"64","reverse-direction":true}],"UNSUBSCRIBE":[],"SESSION_ID":"9a00126c5bf04e29835f7c13fe5ab155"}

Server:

144
{"SUBSCRIBE":[{"name":"bwtest-feed","sub_id":"bandwidth5","server-mode":true}],"UNSUBSCRIBE":[],"SESSION_ID":"9a00126c5bf04e29835f7c13fe5ab155"}

Websockets: Other Endpoints

There is also the following endpoints that not much is known about:

  • onu-list: Lists Optical Network Unit devices.
  • pon-stats: Lists Passive Optical Network stats.
  • nni-stats: Lists Network to Network Interface stats.

Third Party Unofficial APIs

There are a few developers who have worked on creating unofficial APIs:

products/software/edgeos/api.txt · Last modified: 2020/06/21 17:04 by brontide